Charles.Forsyth20060303a828770d19 years agoHistory
765 lines · 19.4 KB · C
RawDownload
/***************************************************************************//*                                                                         *//*  ftcmanag.c                                                             *//*                                                                         *//*    FreeType Cache Manager (body).                                       *//*                                                                         *//*  Copyright 2000-2001, 2002 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_MANAGER_H#include FT_CACHE_INTERNAL_LRU_H#include FT_INTERNAL_OBJECTS_H#include FT_INTERNAL_DEBUG_H#include FT_SIZES_H #include "ftcerror.h"  #undef  FT_COMPONENT#define FT_COMPONENT  trace_cache #define FTC_LRU_GET_MANAGER( lru )  ( (FTC_Manager)(lru)->user_data )    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                    FACE LRU IMPLEMENTATION                    *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/   typedef struct FTC_FaceNodeRec_*  FTC_FaceNode;  typedef struct FTC_SizeNodeRec_*  FTC_SizeNode;    typedef struct  FTC_FaceNodeRec_  {    FT_LruNodeRec  lru;    FT_Face        face;   } FTC_FaceNodeRec;    typedef struct  FTC_SizeNodeRec_  {    FT_LruNodeRec  lru;    FT_Size        size;   } FTC_SizeNodeRec;    FT_CALLBACK_DEF( FT_Error )  ftc_face_node_init( FTC_FaceNode  node,                      FTC_FaceID    face_id,                      FTC_Manager   manager )  {    FT_Error  error;      error = manager->request_face( face_id,                                   manager->library,                                   manager->request_data,                                   &node->face );    if ( !error )    {      /* destroy initial size object; it will be re-created later */      if ( node->face->size )        FT_Done_Size( node->face->size );    }     return error;  }    /* helper function for ftc_face_node_done() */  FT_CALLBACK_DEF( FT_Bool )  ftc_size_node_select( FTC_SizeNode  node,                        FT_Face       face )  {    return FT_BOOL( node->size->face == face );  }    FT_CALLBACK_DEF( void )  ftc_face_node_done( FTC_FaceNode  node,                      FTC_Manager   manager )  {    FT_Face  face    = node->face;      /* we must begin by removing all sizes for the target face */    /* from the manager's list                                 */    FT_LruList_Remove_Selection( manager->sizes_list,                                 (FT_LruNode_SelectFunc)ftc_size_node_select,                                 face );     /* all right, we can discard the face now */    FT_Done_Face( face );    node->face = NULL;  }    FT_CALLBACK_TABLE_DEF  const FT_LruList_ClassRec  ftc_face_list_class =  {    sizeof ( FT_LruListRec ),    (FT_LruList_InitFunc)0,    (FT_LruList_DoneFunc)0,     sizeof ( FTC_FaceNodeRec ),    (FT_LruNode_InitFunc)   ftc_face_node_init,    (FT_LruNode_DoneFunc)   ftc_face_node_done,    (FT_LruNode_FlushFunc)  0,  /* no flushing needed                      */    (FT_LruNode_CompareFunc)0,  /* direct comparison of FTC_FaceID handles */  };    /* documentation is in ftcache.h */   FT_EXPORT_DEF( FT_Error )  FTC_Manager_Lookup_Face( FTC_Manager  manager,                           FTC_FaceID   face_id,                           FT_Face     *aface )  {    FT_Error      error;    FTC_FaceNode  node;      if ( aface == NULL )      return FTC_Err_Bad_Argument;     *aface = NULL;     if ( !manager )      return FTC_Err_Invalid_Cache_Handle;     error = FT_LruList_Lookup( manager->faces_list,                               (FT_LruKey)face_id,                               (FT_LruNode*)&node );    if ( !error )      *aface = node->face;     return error;  }    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                      SIZES LRU IMPLEMENTATION                 *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/    typedef struct  FTC_SizeQueryRec_  {    FT_Face  face;    FT_UInt  width;    FT_UInt  height;   } FTC_SizeQueryRec, *FTC_SizeQuery;    FT_CALLBACK_DEF( FT_Error )  ftc_size_node_init( FTC_SizeNode   node,                      FTC_SizeQuery  query )  {    FT_Face   face = query->face;    FT_Size   size;    FT_Error  error;      node->size = NULL;    error = FT_New_Size( face, &size );    if ( !error )    {      FT_Activate_Size( size );      error = FT_Set_Pixel_Sizes( query->face,                                  query->width,                                  query->height );      if ( error )        FT_Done_Size( size );      else        node->size = size;    }    return error;  }    FT_CALLBACK_DEF( void )  ftc_size_node_done( FTC_SizeNode  node )  {    if ( node->size )    {      FT_Done_Size( node->size );      node->size = NULL;    }  }    FT_CALLBACK_DEF( FT_Error )  ftc_size_node_flush( FTC_SizeNode   node,                       FTC_SizeQuery  query )  {    FT_Size   size = node->size;    FT_Error  error;      if ( size->face == query->face )    {      FT_Activate_Size( size );      error = FT_Set_Pixel_Sizes( query->face, query->width, query->height );      if ( error )      {        FT_Done_Size( size );        node->size = NULL;      }    }    else    {      FT_Done_Size( size );      node->size = NULL;       error = ftc_size_node_init( node, query );    }    return error;  }    FT_CALLBACK_DEF( FT_Bool )  ftc_size_node_compare( FTC_SizeNode   node,                         FTC_SizeQuery  query )  {    FT_Size  size = node->size;      return FT_BOOL( size->face                    == query->face   &&                    (FT_UInt)size->metrics.x_ppem == query->width  &&                    (FT_UInt)size->metrics.y_ppem == query->height );  }    FT_CALLBACK_TABLE_DEF  const FT_LruList_ClassRec  ftc_size_list_class =  {    sizeof ( FT_LruListRec ),    (FT_LruList_InitFunc)0,    (FT_LruList_DoneFunc)0,     sizeof ( FTC_SizeNodeRec ),    (FT_LruNode_InitFunc)   ftc_size_node_init,    (FT_LruNode_DoneFunc)   ftc_size_node_done,    (FT_LruNode_FlushFunc)  ftc_size_node_flush,    (FT_LruNode_CompareFunc)ftc_size_node_compare  };    /* documentation is in ftcache.h */   FT_EXPORT_DEF( FT_Error )  FTC_Manager_Lookup_Size( FTC_Manager  manager,                           FTC_Font     font,                           FT_Face     *aface,                           FT_Size     *asize )  {    FT_Error  error;      /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */    if ( aface )      *aface = 0;     if ( asize )      *asize = 0;     error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );    if ( !error )    {      FTC_SizeQueryRec  query;      FTC_SizeNode      node;        query.face   = *aface;      query.width  = font->pix_width;      query.height = font->pix_height;       error = FT_LruList_Lookup( manager->sizes_list,                                 (FT_LruKey)&query,                                 (FT_LruNode*)&node );      if ( !error )      {        /* select the size as the current one for this face */        FT_Activate_Size( node->size );         if ( asize )          *asize = node->size;      }    }     return error;  }    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                    SET TABLE MANAGEMENT                       *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/   static void  ftc_family_table_init( FTC_FamilyTable  table )  {    table->count   = 0;    table->size    = 0;    table->entries = NULL;    table->free    = FTC_FAMILY_ENTRY_NONE;  }    static void  ftc_family_table_done( FTC_FamilyTable  table,                         FT_Memory        memory )  {    FT_FREE( table->entries );    table->free  = 0;    table->count = 0;    table->size  = 0;  }    FT_EXPORT_DEF( FT_Error )  ftc_family_table_alloc( FTC_FamilyTable   table,                          FT_Memory         memory,                          FTC_FamilyEntry  *aentry )  {    FTC_FamilyEntry  entry;    FT_Error         error = 0;      /* re-allocate table size when needed */    if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size )    {      FT_UInt  old_size = table->size;      FT_UInt  new_size, idx;        if ( old_size == 0 )        new_size = 8;      else      {        new_size = old_size * 2;         /* check for (unlikely) overflow */        if ( new_size < old_size )          new_size = 65534;      }       if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) )        return error;       table->size = new_size;       entry       = table->entries + old_size;      table->free = old_size;       for ( idx = old_size; idx + 1 < new_size; idx++, entry++ )      {        entry->link  = idx + 1;        entry->index = idx;      }       entry->link  = FTC_FAMILY_ENTRY_NONE;      entry->index = idx;    }     if ( table->free != FTC_FAMILY_ENTRY_NONE )    {      entry       = table->entries + table->free;      table->free = entry->link;    }    else if ( table->count < table->size )    {      entry = table->entries + table->count++;    }    else    {      FT_ERROR(( "ftc_family_table_alloc: internal bug!" ));      return FTC_Err_Invalid_Argument;    }     entry->link = FTC_FAMILY_ENTRY_NONE;    table->count++;     *aentry = entry;    return error;  }    FT_EXPORT_DEF( void )  ftc_family_table_free( FTC_FamilyTable  table,                         FT_UInt          idx )  {    /* simply add it to the linked list of free entries */    if ( idx < table->count )    {      FTC_FamilyEntry  entry = table->entries + idx;        if ( entry->link != FTC_FAMILY_ENTRY_NONE )        FT_ERROR(( "ftc_family_table_free: internal bug!\n" ));      else      {        entry->link = table->free;        table->free = entry->index;        table->count--;      }    }  }    /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                    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 = 0;      if ( !library )      return FTC_Err_Invalid_Library_Handle;     memory = library->memory;     if ( FT_NEW( 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;     error = FT_LruList_New( &ftc_face_list_class,                            max_faces,                            manager,                            memory,                            &manager->faces_list );    if ( error )      goto Exit;     error = FT_LruList_New( &ftc_size_list_class,                            max_sizes,                            manager,                            memory,                            &manager->sizes_list );    if ( error )      goto Exit;     manager->library      = library;    manager->max_weight   = max_bytes;    manager->cur_weight   = 0;     manager->request_face = requester;    manager->request_data = req_data; 

Lines 1–500 of 765.