Edit

kc3-lang/freetype/src/cache/ftlru.c

Branch :

  • Show log

    Commit

  • Author : Werner Lemberg
    Date : 2003-06-22 15:33:53
    Hash : 779afe4b
    Message : * src/winfonts/winfnt.c (FNT_Load_Glyph): Use first_char in computation of glyph_index. (FNT_Size_Set_Pixels): To find a strike, first check pixel_height only, then try to find a better hit by comparing pixel_width also. Without this fix it isn't possible to access all strikes. Also compute metrics.max_advance to be in sync with other bitmap drivers. * src/base/ftobjs.c (FT_Set_Char_Size): Remove redundant code. (FT_Set_Pixel_Size): Assign value to `metrics' after validation of arguments. Synchronize computation of height and width for bitmap strikes. The `width' field in the FT_Bitmap_Size structure is now only useful to enumerate different strikes. The `max_advance' field of the FT_Size_Metrics structure should be used to get the (maximum) width of a strike. * src/bdf/bdfdrivr.c (BDF_Face_Init): Don't use AVERAGE_WIDTH for computing `available_sizes->width' but make it always equal to `available_sizes->height'. * src/pcf/pcfread.c (pcf_load_font): Don't use RESOLUTION_X for computing `available_sizes->width' but make it always equal to `available_sizes->height'. * src/truetype/ttdriver.c (Set_Pixel_Sizes): Pass only single argument to function. * src/psnames/psmodule.c (ps_unicode_value): Handle `.' after `uniXXXX' and `uXXXX[X[X]]'. * src/bdf/bdfdrivr.c: s/FT_Err_/BDF_Err/. * src/cache/ftccache.c, src/cache/ftcsbits.c, src/cache/ftlru.c: s/FT_Err_/FTC_Err_/. * src/cff/cffcmap.c: s/FT_Err_/CFF_Err_/. * src/pcf/pcfdrivr.c: s/FT_Err_/PCF_Err_/. * src/psaux/t1cmap.c: Include psauxerr.h. s/FT_Err_/PSaux_Err_/. * src/pshinter/pshnterr.h: New file. * src/pshinter/rules.mk: Updated. * src/pshinter/pshalgo.c, src/pshinter/pshrec.c: Include pshnterr.h. s/FT_Err_/PSH_Err_/. * src/pfr/pfrdrivr.c, src/pfr/pfrobjs.c, src/pfr/pfrsbit.c: s/FT_Err_/PFR_Err_/. * src/sfnt/sfdriver.c, src/sfnt/sfobjs.c, src/sfnt/ttcmap0.c, src/sfnt/ttload.c: s/FT_Err_/SFNT_Err_/. * src/truetype/ttgload.c: s/FT_Err_/TT_Err_/. * src/gzip/ftgzip.c: Load FT_MODULE_ERRORS_H and define FT_ERR_PREFIX and FT_ERR_BASE. s/FT_Err_/Gzip_Err_/.

  • src/cache/ftlru.c
  • /***************************************************************************/
    /*                                                                         */
    /*  ftlru.c                                                                */
    /*                                                                         */
    /*    Simple LRU list-cache (body).                                        */
    /*                                                                         */
    /*  Copyright 2000-2001, 2002, 2003 by                                     */
    /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
    /*                                                                         */
    /*  This file is part of the FreeType project, and may only be used,       */
    /*  modified, and distributed under the terms of the FreeType project      */
    /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
    /*  this file you indicate that you have read the license and              */
    /*  understand and accept it fully.                                        */
    /*                                                                         */
    /***************************************************************************/
    
    
    #include <ft2build.h>
    #include FT_CACHE_H
    #include FT_CACHE_INTERNAL_LRU_H
    #include FT_LIST_H
    #include FT_INTERNAL_OBJECTS_H
    #include FT_INTERNAL_DEBUG_H
    
    #include "ftcerror.h"
    
    
      FT_EXPORT_DEF( FT_Error )
      FT_LruList_New( FT_LruList_Class  clazz,
                      FT_UInt           max_nodes,
                      FT_Pointer        user_data,
                      FT_Memory         memory,
                      FT_LruList       *alist )
      {
        FT_Error    error;
        FT_LruList  list;
    
    
        if ( !alist || !clazz )
          return FTC_Err_Invalid_Argument;
    
        *alist = NULL;
        if ( !FT_ALLOC( list, clazz->list_size ) )
        {
          /* initialize common fields */
          list->clazz      = clazz;
          list->memory     = memory;
          list->max_nodes  = max_nodes;
          list->data       = user_data;
    
          if ( clazz->list_init )
          {
            error = clazz->list_init( list );
            if ( error )
            {
              if ( clazz->list_done )
                clazz->list_done( list );
    
              FT_FREE( list );
            }
          }
    
          *alist = list;
        }
    
        return error;
      }
    
    
      FT_EXPORT_DEF( void )
      FT_LruList_Destroy( FT_LruList  list )
      {
        FT_Memory         memory;
        FT_LruList_Class  clazz;
    
    
        if ( !list )
          return;
    
        memory = list->memory;
        clazz  = list->clazz;
    
        FT_LruList_Reset( list );
    
        if ( clazz->list_done )
          clazz->list_done( list );
    
        FT_FREE( list );
      }
    
    
      FT_EXPORT_DEF( void )
      FT_LruList_Reset( FT_LruList  list )
      {
        FT_LruNode        node;
        FT_LruList_Class  clazz;
        FT_Memory         memory;
    
    
        if ( !list )
          return;
    
        node   = list->nodes;
        clazz  = list->clazz;
        memory = list->memory;
    
        while ( node )
        {
          FT_LruNode  next = node->next;
    
    
          if ( clazz->node_done )
            clazz->node_done( node, list->data );
    
          FT_FREE( node );
          node = next;
        }
    
        list->nodes     = NULL;
        list->num_nodes = 0;
      }
    
    
      FT_EXPORT_DEF( FT_Error )
      FT_LruList_Lookup( FT_LruList   list,
                         FT_LruKey    key,
                         FT_LruNode  *anode )
      {
        FT_Error          error = 0;
        FT_LruNode        node, *pnode;
        FT_LruList_Class  clazz;
        FT_LruNode        result = NULL;
        FT_Memory         memory;
    
    
        if ( !list || !key || !anode )
          return FTC_Err_Invalid_Argument;
    
        pnode  = &list->nodes;
        node   = NULL;
        clazz  = list->clazz;
        memory = list->memory;
    
        if ( clazz->node_compare )
        {
          for (;;)
          {
            node = *pnode;
            if ( node == NULL )
              break;
    
            if ( clazz->node_compare( node, key, list->data ) )
              break;
    
            pnode = &(*pnode)->next;
          }
        }
        else
        {
          for (;;)
          {
            node = *pnode;
            if ( node == NULL )
              break;
    
            if ( node->key == key )
              break;
    
            pnode = &(*pnode)->next;
          }
        }
    
        if ( node )
        {
          /* move element to top of list */
          if ( list->nodes != node )
          {
            *pnode      = node->next;
            node->next  = list->nodes;
            list->nodes = node;
          }
          result = node;
          goto Exit;
        }
    
       /* Since we haven't found the relevant element in our LRU list,
        * we're going to "create" a new one.
        *
        * The following code is a bit special, because it tries to handle
        * out-of-memory conditions (OOM) in an intelligent way.
        *
        * More precisely, if not enough memory is available to create a
        * new node or "flush" an old one, we need to remove the oldest
        * elements from our list, and try again.  Since several tries may
        * be necessary, a loop is needed.
        *
        * This loop will only exit when:
        *
        *   - a new node was successfully created, or an old node flushed
        *   - an error other than FTC_Err_Out_Of_Memory is detected
        *   - the list of nodes is empty, and it isn't possible to create
        *     new nodes
        *
        * On each unsuccessful attempt, one node will be removed from the list.
        *
        */
        
        {
          FT_Int  drop_last = ( list->max_nodes > 0 && 
                                list->num_nodes >= list->max_nodes );
    
          for (;;)
          {
            node = NULL;
    
            /* If "drop_last" is true, we should free the last node in
             * the list to make room for a new one.  Note that we reuse
             * its memory block to save allocation calls.
             */
            if ( drop_last )
            {
             /* find the last node in the list
              */
              pnode = &list->nodes;
              node  = *pnode;
      
              if ( node == NULL )
              {
                FT_ASSERT( list->num_nodes == 0 );
                error = FTC_Err_Out_Of_Memory;
                goto Exit;
              }
    
              FT_ASSERT( list->num_nodes > 0 );
    
              while ( node->next )
              {
                pnode = &node->next;
                node  = *pnode;
              }
      
              /* Remove it from the list, and try to "flush" it.  Doing this will
               * save a significant number of dynamic allocations compared to
               * a classic destroy/create cycle.
               */
              *pnode = NULL;
              list->num_nodes--;
      
              if ( clazz->node_flush )
              {
                error = clazz->node_flush( node, key, list->data );
                if ( !error )
                  goto Success;
    
               /* Note that if an error occured during the flush, we need to
                * finalize it since it is potentially in incomplete state.
                */
              }
    
              /* We finalize, but do not destroy the last node, we
               * simply reuse its memory block!
               */
              if ( clazz->node_done )
                clazz->node_done( node, list->data );
                
              FT_MEM_ZERO( node, clazz->node_size );
            }
            else
            {
             /* Try to allocate a new node when "drop_last" is not TRUE.
              * This usually happens on the first pass, when the LRU list
              * is not already full.
              */
              if ( FT_ALLOC( node, clazz->node_size ) )
                goto Fail;
            }
      
            FT_ASSERT( node != NULL );
    
            node->key = key;
            error = clazz->node_init( node, key, list->data );
            if ( error )
            {
              if ( clazz->node_done )
                clazz->node_done( node, list->data );
    
              FT_FREE( node );
              goto Fail;
            }
    
          Success:
            result = node;
    
            node->next  = list->nodes;
            list->nodes = node;
            list->num_nodes++;
            goto Exit;
      
          Fail:
            if ( error != FTC_Err_Out_Of_Memory )
              goto Exit;
            
            drop_last = 1;
            continue;
          }
        }
    
      Exit:
        *anode = result;
        return error;
      }
    
    
      FT_EXPORT_DEF( void )
      FT_LruList_Remove( FT_LruList  list,
                         FT_LruNode  node )
      {
        FT_LruNode  *pnode;
    
    
        if ( !list || !node )
          return;
    
        pnode = &list->nodes;
        for (;;)
        {
          if ( *pnode == node )
          {
            FT_Memory         memory = list->memory;
            FT_LruList_Class  clazz  = list->clazz;
    
    
            *pnode     = node->next;
            node->next = NULL;
    
            if ( clazz->node_done )
              clazz->node_done( node, list->data );
    
            FT_FREE( node );
            list->num_nodes--;
            break;
          }
    
          pnode = &(*pnode)->next;
        }
      }
    
    
      FT_EXPORT_DEF( void )
      FT_LruList_Remove_Selection( FT_LruList             list,
                                   FT_LruNode_SelectFunc  select_func,
                                   FT_Pointer             select_data )
      {
        FT_LruNode       *pnode, node;
        FT_LruList_Class  clazz;
        FT_Memory         memory;
    
    
        if ( !list || !select_func )
          return;
    
        memory = list->memory;
        clazz  = list->clazz;
        pnode  = &list->nodes;
    
        for (;;)
        {
          node = *pnode;
          if ( node == NULL )
            break;
    
          if ( select_func( node, select_data, list->data ) )
          {
            *pnode     = node->next;
            node->next = NULL;
    
            if ( clazz->node_done )
              clazz->node_done( node, list );
    
            FT_FREE( node );
            list->num_nodes--;
          }
          else
            pnode = &(*pnode)->next;
        }
      }
    
    
    /* END */