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

📄 ftcglyph.c

📁 qt-embedded-2.3.8.tar.gz源码
💻 C
字号:
/***************************************************************************//*                                                                         *//*  ftcglyph.c                                                             *//*                                                                         *//*    FreeType Glyph Image (FT_Glyph) cache (body).                        *//*                                                                         *//*  Copyright 2000 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/cache/ftcglyph.h>#include <freetype/fterrors.h>#include <freetype/ftlist.h>#include <freetype/internal/ftobjs.h>#include <freetype/internal/ftdebug.h>  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                      GLYPH NODES                              *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  /* create a new glyph node, setting its cache index and ref count */  FT_EXPORT_DEF( void )  FTC_GlyphNode_Init( FTC_GlyphNode  node,                                             FTC_GlyphSet   gset,                                             FT_UInt        gindex )  {    FTC_Glyph_Cache      cache = gset->cache;    FTC_CacheNode_Data*  data  = FTC_CACHENODE_TO_DATA_P( &node->root );    data->cache_index = (FT_UShort)cache->root.cache_index;    data->ref_count   = (FT_Short) 0;    node->gset_index  = (FT_UShort)gset->gset_index;    node->glyph_index = (FT_UShort)gindex;  }  /* Important: This function is called from the cache manager to */  /* destroy a given cache node during `cache compression'.  The  */  /* second argument is always `cache.cache_data'.  Thus be       */  /* certain that the function FTC_Glyph_Cache_New() does indeed  */  /* set its `cache_data' field correctly, otherwise bad things   */  /* will happen!                                                 */  FT_EXPORT_DEF( void )  FTC_GlyphNode_Destroy( FTC_GlyphNode    node,                                                FTC_Glyph_Cache  cache )  {    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;    FT_UInt       hash     = node->glyph_index % gset->hash_size;    /* remove the node from its gset's bucket list */    {      FTC_GlyphNode*  pnode = gset->buckets + hash;      FTC_GlyphNode   cur;      for (;;)      {        cur = *pnode;        if ( !cur )        {          /* this should never happen */          FT_ERROR(( "FTC_GlyphNode_Destroy:"                     " trying to delete an unlisted node!" ));          return;        }        if ( cur == node )        {          *pnode = cur->gset_next;          break;        }        pnode = &cur->gset_next;      }    }    /* destroy the node */    gset->clazz->destroy_node( node, gset );  }  /* Important: This function is called from the cache manager to */  /* size a given cache node during `cache compression'.  The     */  /* second argument is always `cache.user_data'.  Thus be        */  /* certain that the function FTC_Glyph_Cache_New() does indeed  */  /* set its `user_data' field correctly, otherwise bad things    */  /* will happen!                                                 */  FT_EXPORT_DEF( FT_ULong )  FTC_GlyphNode_Size( FTC_GlyphNode    node,                                                 FTC_Glyph_Cache  cache )  {    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;    return gset->clazz->size_node( node, gset );  }  FT_CALLBACK_TABLE_DEF  const FTC_CacheNode_Class  ftc_glyph_cache_node_class =  {    (FTC_CacheNode_SizeFunc)   FTC_GlyphNode_Size,    (FTC_CacheNode_DestroyFunc)FTC_GlyphNode_Destroy  };  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                      GLYPH SETS                               *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_EXPORT_DEF( FT_Error )  FTC_GlyphSet_New( FTC_Glyph_Cache  cache,                                               FT_Pointer       type,                                               FTC_GlyphSet    *aset )  {    FT_Error                error;    FT_Memory               memory  = cache->root.memory;    FTC_Manager             manager = cache->root.manager;    FTC_GlyphSet            gset    = 0;    FTC_Glyph_Cache_Class*  gcache_class;    FTC_GlyphSet_Class*     clazz;    gcache_class = (FTC_Glyph_Cache_Class*)cache->root.clazz;    clazz        = gcache_class->gset_class;    *aset = 0;    if ( ALLOC( gset, clazz->gset_byte_size ) )      goto Exit;    gset->cache     = cache;    gset->manager   = manager;    gset->memory    = memory;    gset->hash_size = FTC_GSET_HASH_SIZE_DEFAULT;    gset->clazz     = clazz;    /* allocate buckets table */    if ( ALLOC_ARRAY( gset->buckets, gset->hash_size, FTC_GlyphNode ) )      goto Exit;    /* initialize gset by type if needed */    if ( clazz->init )    {      error = clazz->init( gset, type );      if ( error )        goto Exit;    }    *aset = gset;  Exit:    if ( error && gset )    {      FREE( gset->buckets );      FREE( gset );    }    return error;  }  FT_EXPORT_DEF( void )  FTC_GlyphSet_Destroy( FTC_GlyphSet  gset )  {    FTC_Glyph_Cache      cache        = gset->cache;    FTC_Manager          manager      = cache->root.manager;    FT_List              glyphs_lru   = &manager->global_lru;    FTC_GlyphNode*       bucket       = gset->buckets;    FTC_GlyphNode*       bucket_limit = bucket + gset->hash_size;    FT_Memory            memory       = cache->root.memory;    FTC_GlyphSet_Class*  clazz        = gset->clazz;    /* for each bucket, free the list of glyph nodes */    for ( ; bucket < bucket_limit; bucket++ )    {      FTC_GlyphNode   node = bucket[0];      FTC_GlyphNode   next = 0;      FT_ListNode     lrunode;      for ( ; node; node = next )      {        next    = node->gset_next;        lrunode = FTC_GLYPHNODE_TO_LRUNODE( node );        manager->num_bytes -= clazz->size_node( node, gset );        manager->num_nodes--;        FT_List_Remove( glyphs_lru, lrunode );        clazz->destroy_node( node, gset );      }      bucket[0] = 0;    }    if ( clazz->done )      clazz->done( gset );    FREE( gset->buckets );    FREE( gset );  }  FT_EXPORT_DEF( FT_Error )  FTC_GlyphSet_Lookup_Node(                               FTC_GlyphSet    gset,                               FT_UInt         glyph_index,                               FTC_GlyphNode  *anode )  {    FTC_Glyph_Cache      cache      = gset->cache;    FTC_Manager          manager    = cache->root.manager;    FT_UInt              hash_index = glyph_index % gset->hash_size;    FTC_GlyphNode*       bucket     = gset->buckets + hash_index;    FTC_GlyphNode*       pnode      = bucket;    FTC_GlyphNode        node;    FT_Error             error;    FTC_GlyphSet_Class*  clazz      = gset->clazz;    *anode = 0;    for ( ;; )    {      node = *pnode;      if ( !node )        break;      if ( (FT_UInt)node->glyph_index == glyph_index )      {        /* we found it! -- move glyph to start of the lists */        *pnode          = node->gset_next;        node->gset_next = bucket[0];        bucket[0]       = node;        FT_List_Up( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );        *anode = node;        return 0;      }      /* go to next node in bucket */      pnode = &node->gset_next;    }    /* we didn't found the glyph image, we will now create a new one */    error = clazz->new_node( gset, glyph_index, &node );    if ( error )      goto Exit;    /* insert the node at the start of our bucket list */    node->gset_next = bucket[0];    bucket[0]       = node;    /* insert the node at the start the global LRU glyph list */    FT_List_Insert( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );    manager->num_bytes += clazz->size_node( node, gset );    manager->num_nodes++;    if ( manager->num_bytes > manager->max_bytes )    {      FTC_GlyphNode_Ref   ( node );      FTC_Manager_Compress( manager );      FTC_GlyphNode_Unref ( node );    }    *anode = node;  Exit:    return error;  }  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                   GLYPH SETS LRU CALLBACKS                    *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/#define FTC_GSET_LRU_GET_CACHE( lru )   \          ( (FTC_Glyph_Cache)(lru)->user_data )#define FTC_GSET_LRU_GET_MANAGER( lru ) \          FTC_GSET_LRU_GET_CACHE( lru )->manager#define FTC_LRUNODE_GSET( node )        \          ( (FTC_GlyphSet)(node)->root.data )  FT_CALLBACK_DEF  FT_Error  ftc_glyph_set_lru_init( FT_Lru      lru,                                    FT_LruNode  node )  {    FTC_Glyph_Cache  cache = FTC_GSET_LRU_GET_CACHE( lru );    FT_Error         error;    FTC_GlyphSet     gset;    error = FTC_GlyphSet_New( cache, (FT_Pointer)node->key, &gset );    if ( !error )    {      /* good, now set the gset index within the gset object */      gset->gset_index = node - lru->nodes;      node->root.data  = gset;    }    return error;  }  FT_CALLBACK_DEF  void  ftc_glyph_set_lru_done( FT_Lru      lru,                                FT_LruNode  node )  {    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );    FT_UNUSED( lru );    FTC_GlyphSet_Destroy( gset );  }  FT_CALLBACK_DEF  FT_Bool  ftc_glyph_set_lru_compare( FT_LruNode  node,                                      FT_LruKey   key )  {    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );    return gset->clazz->compare( gset, (FT_Pointer)key );  }  FT_CALLBACK_TABLE_DEF  const FT_Lru_Class  ftc_glyph_set_lru_class =  {    sizeof( FT_LruRec ),    ftc_glyph_set_lru_init,    ftc_glyph_set_lru_done,    0,  /* no flush */    ftc_glyph_set_lru_compare  };  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                      GLYPH CACHE OBJECTS                      *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/  FT_EXPORT_DEF( FT_Error )  FTC_Glyph_Cache_Init( FTC_Glyph_Cache  cache )  {    FT_Memory  memory = cache->root.memory;    FT_Error   error;    FTC_Glyph_Cache_Class*  gcache_clazz;    /* set up root node_class to be used by manager */    cache->root.node_clazz =      (FTC_CacheNode_Class*)&ftc_glyph_cache_node_class;    /* setup the `compare' shortcut */    gcache_clazz   = (FTC_Glyph_Cache_Class*)cache->root.clazz;    cache->compare = gcache_clazz->gset_class->compare;    /* The following is extremely important for ftc_destroy_glyph_image() */    /* to work properly, as the second parameter that is sent to it       */    /* through the cache manager is `cache_data' and must be set to       */    /* `cache' here.                                                      */    /*                                                                    */    cache->root.cache_data = cache;    error = FT_Lru_New( &ftc_glyph_set_lru_class,                        FTC_MAX_GLYPH_SETS,                        cache,                        memory,                        1, /* pre_alloc == TRUE */                        &cache->gsets_lru );    return error;  }  FT_EXPORT_DEF( void )  FTC_Glyph_Cache_Done( FTC_Glyph_Cache  cache )  {    /* discard glyph sets */    FT_Lru_Done( cache->gsets_lru );  }  FT_EXPORT_DEF( FT_Error )  FTC_Glyph_Cache_Lookup( FTC_Glyph_Cache  cache,                                                     FT_Pointer       type,                                                     FT_UInt          gindex,                                                     FTC_GlyphNode   *anode )  {    FT_Error       error;    FTC_GlyphSet   gset;    FTC_GlyphNode  node;    FTC_Manager    manager;    /* check for valid `desc' delayed to FT_Lru_Lookup() */    if ( !cache || !anode )      return FT_Err_Invalid_Argument;    *anode = 0;    gset   = cache->last_gset;    if ( !gset || !cache->compare( gset, type ) )    {      error = FT_Lru_Lookup( cache->gsets_lru,                             (FT_LruKey)type,                             (FT_Pointer*)&gset );      cache->last_gset = gset;      if ( error )        goto Exit;    }    error = FTC_GlyphSet_Lookup_Node( gset, gindex, &node );    if ( error )      goto Exit;    /* now compress the manager's cache pool if needed */    manager = cache->root.manager;    if ( manager->num_bytes > manager->max_bytes )    {      FTC_GlyphNode_Ref   ( node );      FTC_Manager_Compress( manager );      FTC_GlyphNode_Unref ( node );    }    *anode = node;  Exit:    return error;  }/* END */

⌨️ 快捷键说明

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