Edit

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

Branch :

  • Show log

    Commit

  • Author : Alexei Podtelezhnikov
    Date : 2024-04-29 17:54:30
    Hash : a209e1ad
    Message : [cache] Remove unused `node_reset`. * src/cache/ftcmru.h (FTC_MruListClassRec): Remove `node_reset` field. * src/cache/ftcbasic.c (ftc_basic_{image,sbit}_family_class): Ditto. * src/cache/ftcmanag.c (ftc_face_list_class): Ditto. (ftc_size_node_reset): Remove function. * src/cache/ftcglyph.h: Fix comment.

  • src/cache/ftcmanag.c
  • /****************************************************************************
     *
     * ftcmanag.c
     *
     *   FreeType Cache Manager (body).
     *
     * Copyright (C) 2000-2024 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 <freetype/ftcache.h>
    #include "ftcmanag.h"
    #include <freetype/internal/ftobjs.h>
    #include <freetype/internal/ftdebug.h>
    #include <freetype/ftsizes.h>
    
    #include "ftcerror.h"
    
    
    #undef  FT_COMPONENT
    #define FT_COMPONENT  cache
    
    
      static FT_Error
      ftc_scaler_lookup_size( FTC_Manager  manager,
                              FTC_Scaler   scaler,
                              FT_Size     *asize )
      {
        FT_Face   face;
        FT_Size   size = NULL;
        FT_Error  error;
    
    
        error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
        if ( error )
          goto Exit;
    
        error = FT_New_Size( face, &size );
        if ( error )
          goto Exit;
    
        FT_Activate_Size( size );
    
        if ( scaler->pixel )
          error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
        else
          error = FT_Set_Char_Size( face,
                                    (FT_F26Dot6)scaler->width,
                                    (FT_F26Dot6)scaler->height,
                                    scaler->x_res,
                                    scaler->y_res );
        if ( error )
        {
          FT_Done_Size( size );
          size = NULL;
        }
    
      Exit:
        *asize = size;
        return error;
      }
    
    
      typedef struct  FTC_SizeNodeRec_
      {
        FTC_MruNodeRec  node;
        FT_Size         size;
        FTC_ScalerRec   scaler;
    
      } FTC_SizeNodeRec, *FTC_SizeNode;
    
    #define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
    
    
      FT_CALLBACK_DEF( void )
      ftc_size_node_done( FTC_MruNode  ftcnode,
                          FT_Pointer   data )
      {
        FTC_SizeNode  node = (FTC_SizeNode)ftcnode;
        FT_UNUSED( data );
    
    
        FT_Done_Size( node->size );
      }
    
    
      FT_CALLBACK_DEF( FT_Bool )
      ftc_size_node_compare( FTC_MruNode  ftcnode,
                             FT_Pointer   ftcscaler )
      {
        FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
        FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
        FTC_Scaler    scaler0 = &node->scaler;
    
    
        if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
        {
          FT_Activate_Size( node->size );
          return 1;
        }
        return 0;
      }
    
    
      FT_CALLBACK_DEF( FT_Error )
      ftc_size_node_init( FTC_MruNode  ftcnode,
                          FT_Pointer   ftcscaler,
                          FT_Pointer   ftcmanager )
      {
        FT_Error      error;
        FT_Size       size;
        FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
        FTC_Scaler    scaler  = (FTC_Scaler)ftcscaler;
        FTC_Manager   manager = (FTC_Manager)ftcmanager;
    
    
        error = ftc_scaler_lookup_size( manager, scaler, &size );
        if ( !error )
        {
          node->size   = size;
          node->scaler = scaler[0];
        }
    
        return error;
      }
    
    
      static
      const FTC_MruListClassRec  ftc_size_list_class =
      {
        sizeof ( FTC_SizeNodeRec ),
    
        ftc_size_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
        ftc_size_node_init,     /* FTC_MruNode_InitFunc     node_init    */
        ftc_size_node_done      /* FTC_MruNode_DoneFunc     node_done    */
      };
    
    
      /* helper function used by ftc_face_node_done */
      static FT_Bool
      ftc_size_node_compare_faceid( FTC_MruNode  ftcnode,
                                    FT_Pointer   ftcface_id )
      {
        FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
        FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
    
    
        return FT_BOOL( node->scaler.face_id == face_id );
      }
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( FT_Error )
      FTC_Manager_LookupSize( FTC_Manager  manager,
                              FTC_Scaler   scaler,
                              FT_Size     *asize )
      {
        FT_Error     error;
        FTC_MruNode  mrunode;
    
    
        if ( !asize || !scaler )
          return FT_THROW( Invalid_Argument );
    
        *asize = NULL;
    
        if ( !manager )
          return FT_THROW( Invalid_Cache_Handle );
    
    #ifdef FTC_INLINE
    
        FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
                                mrunode, error );
    
    #else
        error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
    #endif
    
        if ( !error )
          *asize = FTC_SIZE_NODE( mrunode )->size;
    
        return error;
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                    FACE MRU IMPLEMENTATION                    *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
      typedef struct  FTC_FaceNodeRec_
      {
        FTC_MruNodeRec  node;
        FTC_FaceID      face_id;
        FT_Face         face;
    
      } FTC_FaceNodeRec, *FTC_FaceNode;
    
    #define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
    
    
      FT_CALLBACK_DEF( FT_Error )
      ftc_face_node_init( FTC_MruNode  ftcnode,
                          FT_Pointer   ftcface_id,
                          FT_Pointer   ftcmanager )
      {
        FT_Error      error;
        FT_Face       face;
        FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
        FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
        FTC_Manager   manager = (FTC_Manager)ftcmanager;
    
    
        error = manager->request_face( face_id,
                                       manager->library,
                                       manager->request_data,
                                       &face );
        if ( !error )
        {
          /* destroy initial size object; it will be re-created later */
          if ( face->size )
            FT_Done_Size( face->size );
    
          node->face    = face;
          node->face_id = face_id;
        }
    
        return error;
      }
    
    
      FT_CALLBACK_DEF( void )
      ftc_face_node_done( FTC_MruNode  ftcnode,
                          FT_Pointer   ftcmanager )
      {
        FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
        FTC_Manager   manager = (FTC_Manager)ftcmanager;
    
    
        /* we must begin by removing all scalers for the target face */
        /* from the manager's list                                   */
        FTC_MruList_RemoveSelection( &manager->sizes,
                                     ftc_size_node_compare_faceid,
                                     node->face_id );
    
        /* all right, we can discard the face now */
        FT_Done_Face( node->face );
        node->face    = NULL;
        node->face_id = NULL;
      }
    
    
      FT_CALLBACK_DEF( FT_Bool )
      ftc_face_node_compare( FTC_MruNode  ftcnode,
                             FT_Pointer   ftcface_id )
      {
        FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
        FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
    
    
        return FT_BOOL( node->face_id == face_id );
      }
    
    
      static
      const FTC_MruListClassRec  ftc_face_list_class =
      {
        sizeof ( FTC_FaceNodeRec),
    
        ftc_face_node_compare,  /* FTC_MruNode_CompareFunc  node_compare */
        ftc_face_node_init,     /* FTC_MruNode_InitFunc     node_init    */
        ftc_face_node_done      /* FTC_MruNode_DoneFunc     node_done    */
      };
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( FT_Error )
      FTC_Manager_LookupFace( FTC_Manager  manager,
                              FTC_FaceID   face_id,
                              FT_Face     *aface )
      {
        FT_Error     error;
        FTC_MruNode  mrunode;
    
    
        if ( !aface )
          return FT_THROW( Invalid_Argument );
    
        *aface = NULL;
    
        if ( !manager )
          return FT_THROW( Invalid_Cache_Handle );
    
        /* we break encapsulation for the sake of speed */
    #ifdef FTC_INLINE
    
        FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
                                mrunode, error );
    
    #else
        error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
    #endif
    
        if ( !error )
          *aface = FTC_FACE_NODE( mrunode )->face;
    
        return error;
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                    CACHE MANAGER ROUTINES                     *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( FT_Error )
      FTC_Manager_New( FT_Library          library,
                       FT_UInt             max_faces,
                       FT_UInt             max_sizes,
                       FT_ULong            max_bytes,
                       FTC_Face_Requester  requester,
                       FT_Pointer          req_data,
                       FTC_Manager        *amanager )
      {
        FT_Error     error;
        FT_Memory    memory;
        FTC_Manager  manager = NULL;
    
    
        if ( !library )
          return FT_THROW( Invalid_Library_Handle );
    
        if ( !amanager || !requester )
          return FT_THROW( Invalid_Argument );
    
        memory = library->memory;
    
        if ( FT_QNEW( manager ) )
          goto Exit;
    
        if ( max_faces == 0 )
          max_faces = FTC_MAX_FACES_DEFAULT;
    
        if ( max_sizes == 0 )
          max_sizes = FTC_MAX_SIZES_DEFAULT;
    
        if ( max_bytes == 0 )
          max_bytes = FTC_MAX_BYTES_DEFAULT;
    
        manager->library      = library;
        manager->memory       = memory;
        manager->max_weight   = max_bytes;
        manager->cur_weight   = 0;
    
        manager->request_face = requester;
        manager->request_data = req_data;
    
        FTC_MruList_Init( &manager->faces,
                          &ftc_face_list_class,
                          max_faces,
                          manager,
                          memory );
    
        FTC_MruList_Init( &manager->sizes,
                          &ftc_size_list_class,
                          max_sizes,
                          manager,
                          memory );
    
        manager->nodes_list = NULL;
        manager->num_nodes  = 0;
        manager->num_caches = 0;
    
        *amanager = manager;
    
      Exit:
        return error;
      }
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( void )
      FTC_Manager_Done( FTC_Manager  manager )
      {
        FT_Memory  memory;
        FT_UInt    idx;
    
    
        if ( !manager || !manager->library )
          return;
    
        memory = manager->memory;
    
        /* now discard all caches */
        for ( idx = manager->num_caches; idx-- > 0; )
        {
          FTC_Cache  cache = manager->caches[idx];
    
    
          if ( cache )
          {
            cache->clazz.cache_done( cache );
            FT_FREE( cache );
          }
        }
    
        /* discard faces and sizes */
        FTC_MruList_Done( &manager->sizes );
        FTC_MruList_Done( &manager->faces );
    
        FT_FREE( manager );
      }
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( void )
      FTC_Manager_Reset( FTC_Manager  manager )
      {
        if ( !manager )
          return;
    
        FTC_MruList_Reset( &manager->sizes );
        FTC_MruList_Reset( &manager->faces );
    
        FTC_Manager_FlushN( manager, manager->num_nodes );
      }
    
    
    #ifdef FT_DEBUG_ERROR
    
      static void
      FTC_Manager_Check( FTC_Manager  manager )
      {
        FTC_Node  node, first;
    
    
        first = manager->nodes_list;
    
        /* check node weights */
        if ( first )
        {
          FT_Offset  weight = 0;
    
    
          node = first;
    
          do
          {
            FTC_Cache  cache = manager->caches[node->cache_index];
    
    
            if ( node->cache_index >= manager->num_caches )
              FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %hu\n",
                          node->cache_index ));
            else
              weight += cache->clazz.node_weight( node, cache );
    
            node = FTC_NODE_NEXT( node );
    
          } while ( node != first );
    
          if ( weight != manager->cur_weight )
            FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
                        manager->cur_weight, weight ));
        }
    
        /* check circular list */
        if ( first )
        {
          FT_UFast  count = 0;
    
    
          node = first;
          do
          {
            count++;
            node = FTC_NODE_NEXT( node );
    
          } while ( node != first );
    
          if ( count != manager->num_nodes )
            FT_TRACE0(( "FTC_Manager_Check:"
                        " invalid cache node count %u instead of %u\n",
                        manager->num_nodes, count ));
        }
      }
    
    #endif /* FT_DEBUG_ERROR */
    
    
      /* `Compress' the manager's data, i.e., get rid of old cache nodes */
      /* that are not referenced anymore in order to limit the total     */
      /* memory used by the cache.                                       */
    
      /* documentation is in ftcmanag.h */
    
      FT_LOCAL_DEF( void )
      FTC_Manager_Compress( FTC_Manager  manager )
      {
        FTC_Node   node, prev, first;
    
    
        if ( !manager )
          return;
    
        first = manager->nodes_list;
    
    #ifdef FT_DEBUG_ERROR
        FTC_Manager_Check( manager );
    
        FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %u\n",
                    manager->cur_weight, manager->max_weight,
                    manager->num_nodes ));
    #endif
    
        if ( manager->cur_weight < manager->max_weight || !first )
          return;
    
        /* go to last node -- it's a circular list */
        prev = FTC_NODE_PREV( first );
        do
        {
          node = prev;
          prev = FTC_NODE_PREV( node );
    
          if ( node->ref_count <= 0 )
            ftc_node_destroy( node, manager );
    
        } while ( node != first && manager->cur_weight > manager->max_weight );
      }
    
    
      /* documentation is in ftcmanag.h */
    
      FT_LOCAL_DEF( FT_Error )
      FTC_Manager_RegisterCache( FTC_Manager      manager,
                                 FTC_CacheClass   clazz,
                                 FTC_Cache       *acache )
      {
        FT_Error   error = FT_ERR( Invalid_Argument );
        FTC_Cache  cache = NULL;
    
    
        if ( manager && clazz && acache )
        {
          FT_Memory  memory = manager->memory;
    
    
          if ( manager->num_caches >= FTC_MAX_CACHES )
          {
            error = FT_THROW( Too_Many_Caches );
            FT_ERROR(( "FTC_Manager_RegisterCache:"
                       " too many registered caches\n" ));
            goto Exit;
          }
    
          if ( !FT_QALLOC( cache, clazz->cache_size ) )
          {
            cache->manager   = manager;
            cache->memory    = memory;
            cache->clazz     = clazz[0];
            cache->org_class = clazz;
    
            /* THIS IS VERY IMPORTANT!  IT WILL WRETCH THE MANAGER */
            /* IF IT IS NOT SET CORRECTLY                          */
            cache->index = manager->num_caches;
    
            error = clazz->cache_init( cache );
            if ( error )
            {
              clazz->cache_done( cache );
              FT_FREE( cache );
              goto Exit;
            }
    
            manager->caches[manager->num_caches++] = cache;
          }
        }
    
      Exit:
        if ( acache )
          *acache = cache;
        return error;
      }
    
    
      FT_LOCAL_DEF( FT_UInt )
      FTC_Manager_FlushN( FTC_Manager  manager,
                          FT_UInt      count )
      {
        FTC_Node  first = manager->nodes_list;
        FTC_Node  prev, node;
        FT_UInt   result = 0;
    
    
        /* try to remove `count' nodes from the list */
        if ( !first || !count )
          return result;
    
        /* go to last node -- it's a circular list */
        prev = FTC_NODE_PREV( first );
        do
        {
          node = prev;
          prev = FTC_NODE_PREV( node );
    
          /* don't touch locked nodes */
          if ( node->ref_count <= 0 )
          {
            ftc_node_destroy( node, manager );
            result++;
          }
        } while ( node != first && result < count );
    
        return result;
      }
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( void )
      FTC_Manager_RemoveFaceID( FTC_Manager  manager,
                                FTC_FaceID   face_id )
      {
        FT_UInt  nn;
    
    
        if ( !manager )
          return;
    
        /* this will remove all FTC_SizeNode that correspond to
         * the face_id as well
         */
        FTC_MruList_RemoveSelection( &manager->faces,
                                     ftc_face_node_compare,
                                     face_id );
    
        for ( nn = 0; nn < manager->num_caches; nn++ )
          FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
      }
    
    
      /* documentation is in ftcache.h */
    
      FT_EXPORT_DEF( void )
      FTC_Node_Unref( FTC_Node     node,
                      FTC_Manager  manager )
      {
        if ( node                                    &&
             manager                                 &&
             node->cache_index < manager->num_caches )
          node->ref_count--;
      }
    
    
    /* END */