⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftccache.c

📁 下载来的一个看图软件的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************//*                                                                         *//*  ftccache.c                                                             *//*                                                                         *//*    The FreeType internal cache interface (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_MANAGER_H#include FT_INTERNAL_OBJECTS_H#include FT_INTERNAL_DEBUG_H#include "ftcerror.h"#define FTC_HASH_MAX_LOAD  2#define FTC_HASH_MIN_LOAD  1#define FTC_HASH_SUB_LOAD  ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )/* this one _must_ be a power of 2! */#define FTC_HASH_INITIAL_SIZE  8  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                   CACHE NODE DEFINITIONS                      *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_EXPORT_DEF( void )  ftc_node_done( FTC_Node   node,                 FTC_Cache  cache )  {    FTC_Family       family;    FTC_FamilyEntry  entry;    entry  = cache->manager->families.entries + node->fam_index;    family = entry->family;    /* remove from parent set table - eventually destroy the set */    if ( --family->num_nodes == 0 )      FT_LruList_Remove( cache->families, (FT_LruNode) family );  }  /* add a new node to the head of the manager's circular MRU list */  static void  ftc_node_mru_link( FTC_Node     node,                     FTC_Manager  manager )  {    FTC_Node  first = manager->nodes_list;    if ( first )    {      FTC_Node  last = first->mru_prev;      FT_ASSERT( last->mru_next == first );      node->mru_prev = last;      node->mru_next = first;      last->mru_next  = node;      first->mru_prev = node;    }    else    {      FT_ASSERT( manager->num_nodes == 0 );      node->mru_next = node;      node->mru_prev = node;    }    manager->nodes_list = node;    manager->num_nodes++;  }  /* remove a node from the manager's MRU list */  static void  ftc_node_mru_unlink( FTC_Node     node,                       FTC_Manager  manager )  {    FTC_Node  first = manager->nodes_list;    FTC_Node  prev  = node->mru_prev;    FTC_Node  next  = node->mru_next;    FT_ASSERT( first != NULL && manager->num_nodes > 0 );    FT_ASSERT( next->mru_prev == node );    FT_ASSERT( prev->mru_next == node );    next->mru_prev = prev;    prev->mru_next = next;    if ( node == first )    {      /* this is the last node in the list; update its head pointer */      if ( node == next )        manager->nodes_list = NULL;      else        manager->nodes_list = next;    }    node->mru_next = NULL;    node->mru_prev = NULL;    manager->num_nodes--;  }  /* move a node to the head of the manager's MRU list */  static void  ftc_node_mru_up( FTC_Node     node,                   FTC_Manager  manager )  {    FTC_Node  first = manager->nodes_list;    if ( node != first )    {      FTC_Node  prev = node->mru_prev;      FTC_Node  next = node->mru_next;      FTC_Node  last;      prev->mru_next = next;      next->mru_prev = prev;      last            = first->mru_prev;      node->mru_next  = first;      node->mru_prev  = last;      first->mru_prev = node;      last->mru_next  = node;      manager->nodes_list = node;    }  }  /* remove a node from its cache's hash table */  static FT_Error  ftc_node_hash_unlink( FTC_Node   node,                        FTC_Cache  cache )  {    FT_Error   error = 0;    FTC_Node  *pnode;    FT_UInt    idx, num_buckets;    idx = (FT_UInt)( node->hash & cache->mask );    if ( idx < cache->p )      idx = (FT_UInt)( node->hash & ( 2 * cache->mask + 1 ) );    pnode = cache->buckets + idx;    for (;;)    {      if ( *pnode == NULL )      {        FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" ));        return FTC_Err_Ok;      }      if ( *pnode == node )      {        *pnode     = node->link;        node->link = NULL;        break;      }      pnode = &(*pnode)->link;    }    num_buckets = ( cache->p + cache->mask + 1 );    if ( ++cache->slack > (FT_Long)num_buckets * FTC_HASH_SUB_LOAD )    {      FT_UInt    p         = cache->p;      FT_UInt    mask      = cache->mask;      FT_UInt    old_index = p + mask;      FTC_Node*  pold;      if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )        goto Exit;      if ( p == 0 )      {        FT_Memory  memory = cache->memory;        cache->mask >>= 1;        p             = cache->mask;        if ( FT_RENEW_ARRAY( cache->buckets, ( mask + 1 ) * 2, (mask+1) ) )        {          FT_ERROR(( "ftc_node_hash_unlink: couldn't shunk buckets!\n" ));          goto Exit;        }      }      else        p--;      pnode = cache->buckets + p;      while ( *pnode )        pnode = &(*pnode)->link;      pold   = cache->buckets + old_index;      *pnode = *pold;      *pold  = NULL;      cache->slack -= FTC_HASH_MAX_LOAD;      cache->p      = p;    }  Exit:    return error;  }  /* add a node to the "top" of its cache's hash table */  static FT_Error  ftc_node_hash_link( FTC_Node   node,                      FTC_Cache  cache )  {    FTC_Node  *pnode;    FT_UInt    idx;    FT_Error   error = 0;    idx = (FT_UInt)( node->hash & cache->mask );    if ( idx < cache->p )      idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) );    pnode = cache->buckets + idx;    node->link = *pnode;    *pnode     = node;    if ( --cache->slack < 0 )    {      FT_UInt    p     = cache->p;      FT_UInt    mask  = cache->mask;      FTC_Node   new_list;      /* split a single bucket */      new_list = NULL;      pnode    = cache->buckets + p;      for (;;)      {        node = *pnode;        if ( node == NULL )          break;        if ( node->hash & ( mask + 1 ) )        {          *pnode     = node->link;          node->link = new_list;          new_list   = node;        }        else          pnode = &node->link;      }      cache->buckets[p + mask + 1] = new_list;      cache->slack += FTC_HASH_MAX_LOAD;      if ( p >= mask )      {        FT_Memory  memory = cache->memory;        if ( FT_RENEW_ARRAY( cache->buckets,                             ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) )        {          FT_ERROR(( "ftc_node_hash_link: couldn't expand buckets!\n" ));          goto Exit;        }        cache->mask = 2 * mask + 1;        cache->p    = 0;      }      else        cache->p = p + 1;    }  Exit:    return error;  }  /* remove a node from the cache manager */  FT_EXPORT_DEF( void )  ftc_node_destroy( FTC_Node     node,                    FTC_Manager  manager )  {    FT_Memory        memory  = manager->library->memory;    FTC_Cache        cache;    FTC_FamilyEntry  entry;    FTC_Cache_Class  clazz;#ifdef FT_DEBUG_ERROR    /* find node's cache */    if ( node->fam_index >= manager->families.count )    {      FT_ERROR(( "ftc_node_destroy: invalid node handle\n" ));      return;    }#endif    entry = manager->families.entries + node->fam_index;    cache = entry->cache;#ifdef FT_DEBUG_ERROR    if ( cache == NULL )    {      FT_ERROR(( "ftc_node_destroy: invalid node handle\n" ));      return;    }#endif    clazz = cache->clazz;    manager->cur_weight -= clazz->node_weight( node, cache );    /* remove node from mru list */    ftc_node_mru_unlink( node, manager );    /* remove node from cache's hash table */    ftc_node_hash_unlink( node, cache );    /* now finalize it */    if ( clazz->node_done )      clazz->node_done( node, cache );    FT_FREE( node );#if 0    /* check, just in case of general corruption :-) */    if ( manager->num_nodes == 0 )      FT_ERROR(( "ftc_node_destroy: invalid cache node count! = %d\n",                  manager->num_nodes ));#endif  }  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                   CACHE FAMILY DEFINITIONS                    *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_EXPORT_DEF( FT_Error )  ftc_family_init( FTC_Family  family,                   FTC_Query   query,                   FTC_Cache   cache )  {    FT_Error         error;    FTC_Manager      manager = cache->manager;    FT_Memory        memory  = manager->library->memory;    FTC_FamilyEntry  entry;    family->cache     = cache;    family->num_nodes = 0;    /* now add to manager's family table */    error = ftc_family_table_alloc( &manager->families, memory, &entry );    if ( !error )    {      entry->cache      = cache;      entry->family     = family;      family->fam_index = entry->index;      query->family = family;   /* save family in query */    }    return error;  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -