parent
64e6f5b5a7
commit
781072441e
18 changed files with 2336 additions and 2282 deletions
@ -1,271 +1,271 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftccache.h */ |
||||
/* */ |
||||
/* FreeType internal cache interface (specification). */ |
||||
/* */ |
||||
/* 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCCACHE_H__ |
||||
#define __FTCCACHE_H__ |
||||
|
||||
|
||||
#include FT_CACHE_INTERNAL_MRU_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/* handle to cache object */ |
||||
typedef struct FTC_CacheRec_* FTC_Cache; |
||||
|
||||
/* handle to cache class */ |
||||
typedef const struct FTC_CacheClassRec_* FTC_CacheClass; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** CACHE NODE DEFINITIONS *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Each cache controls one or more cache nodes. Each node is part of */ |
||||
/* the global_lru list of the manager. Its `data' field however is used */ |
||||
/* as a reference count for now. */ |
||||
/* */ |
||||
/* A node can be anything, depending on the type of information held by */ |
||||
/* the cache. It can be an individual glyph image, a set of bitmaps */ |
||||
/* glyphs for a given size, some metrics, etc. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
/* structure size should be 20 bytes on 32-bits machines */ |
||||
typedef struct FTC_NodeRec_ |
||||
{ |
||||
FTC_MruNodeRec mru; /* circular mru list pointer */ |
||||
FTC_Node link; /* used for hashing */ |
||||
FT_UInt32 hash; /* used for hashing too */ |
||||
FT_UShort cache_index; /* index of cache the node belongs to */ |
||||
FT_Short ref_count; /* reference count for this node */ |
||||
|
||||
} FTC_NodeRec; |
||||
|
||||
|
||||
#define FTC_NODE( x ) ( (FTC_Node)(x) ) |
||||
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) ) |
||||
|
||||
#define FTC_NODE__NEXT(x) FTC_NODE( (x)->mru.next ) |
||||
#define FTC_NODE__PREV(x) FTC_NODE( (x)->mru.prev ) |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* These functions are exported so that they can be called from */ |
||||
/* user-provided cache classes; otherwise, they are really part of the */ |
||||
/* cache sub-system internals. */ |
||||
/* */ |
||||
|
||||
/* reserved for manager's use */ |
||||
FT_EXPORT( void ) |
||||
ftc_node_destroy( FTC_Node node, |
||||
FTC_Manager manager ); |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** CACHE DEFINITIONS *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
/* initialize a new cache node */ |
||||
typedef FT_Error |
||||
(*FTC_Node_NewFunc)( FTC_Node *pnode, |
||||
FT_Pointer query, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef FT_ULong |
||||
(*FTC_Node_WeightFunc)( FTC_Node node, |
||||
FTC_Cache cache ); |
||||
|
||||
/* compare a node to a given key pair */ |
||||
typedef FT_Bool |
||||
(*FTC_Node_CompareFunc)( FTC_Node node, |
||||
FT_Pointer key, |
||||
FTC_Cache cache ); |
||||
|
||||
|
||||
typedef void |
||||
(*FTC_Node_FreeFunc)( FTC_Node node, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_Cache_InitFunc)( FTC_Cache cache ); |
||||
|
||||
typedef void |
||||
(*FTC_Cache_DoneFunc)( FTC_Cache cache ); |
||||
|
||||
|
||||
typedef struct FTC_CacheClassRec_ |
||||
{ |
||||
FTC_Node_NewFunc node_new; |
||||
FTC_Node_WeightFunc node_weight; |
||||
FTC_Node_CompareFunc node_compare; |
||||
FTC_Node_CompareFunc node_remove_faceid; |
||||
FTC_Node_FreeFunc node_free; |
||||
|
||||
FT_UInt cache_size; |
||||
FTC_Cache_InitFunc cache_init; |
||||
FTC_Cache_DoneFunc cache_done; |
||||
|
||||
} FTC_CacheClassRec; |
||||
|
||||
|
||||
/* each cache really implements a dynamic hash table to manage its nodes */ |
||||
typedef struct FTC_CacheRec_ |
||||
{ |
||||
FT_UFast p; |
||||
FT_UFast mask; |
||||
FT_Long slack; |
||||
FTC_Node* buckets; |
||||
|
||||
FTC_CacheClassRec clazz; /* local copy, for speed */ |
||||
|
||||
FTC_Manager manager; |
||||
FT_Memory memory; |
||||
FT_UInt index; /* in manager's table */ |
||||
|
||||
FTC_CacheClass org_class; /* original class pointer */ |
||||
|
||||
} FTC_CacheRec; |
||||
|
||||
|
||||
#define FTC_CACHE( x ) ( (FTC_Cache)(x) ) |
||||
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) ) |
||||
|
||||
|
||||
/* default cache initialize */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_Init( FTC_Cache cache ); |
||||
|
||||
/* default cache finalizer */ |
||||
FT_EXPORT( void ) |
||||
FTC_Cache_Done( FTC_Cache cache ); |
||||
|
||||
/* Call this function to lookup the cache. If no corresponding
|
||||
* node is found, a new one is automatically created. This function |
||||
* is capable of flushing the cache adequately to make room for the |
||||
* new cache object. |
||||
*/ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_Lookup( FTC_Cache cache, |
||||
FT_UInt32 hash, |
||||
FT_Pointer query, |
||||
FTC_Node *anode ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_NewNode( FTC_Cache cache, |
||||
FT_UInt32 hash, |
||||
FT_Pointer query, |
||||
FTC_Node *anode ); |
||||
|
||||
/* Remove all nodes that relate to a given face_id. This is useful
|
||||
* when un-installing fonts. Note that if a cache node relates to |
||||
* the face_id, but is locked (i.e., has 'ref_count > 0'), the node |
||||
* will _not_ be destroyed, but its internal face_id reference will |
||||
* be modified. |
||||
* |
||||
* The final result will be that the node will never come back |
||||
* in further lookup requests, and will be flushed on demand from |
||||
* the cache normally when its reference count reaches 0. |
||||
*/ |
||||
FT_EXPORT( void ) |
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache, |
||||
FTC_FaceID face_id ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_Node *_bucket, *_pnode, _node; \
|
||||
FTC_Cache _cache = FTC_CACHE(cache); \
|
||||
FT_UInt32 _hash = (FT_UInt32)(hash); \
|
||||
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
|
||||
FT_UInt _idx; \
|
||||
\
|
||||
\
|
||||
error = 0; \
|
||||
_idx = _hash & _cache->mask; \
|
||||
if ( _idx < _cache->p ) \
|
||||
_idx = _hash & (_cache->mask*2 + 1); \
|
||||
\
|
||||
_bucket = _pnode = _cache->buckets + _idx; \
|
||||
for (;;) \
|
||||
{ \
|
||||
_node = *_pnode; \
|
||||
if ( _node == NULL ) \
|
||||
goto _NewNode; \
|
||||
\
|
||||
if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
|
||||
break; \
|
||||
\
|
||||
_pnode = &_node->link; \
|
||||
} \
|
||||
\
|
||||
if ( _node != *_bucket ) \
|
||||
{ \
|
||||
*_pnode = _node->link; \
|
||||
_node->link = *_bucket; \
|
||||
*_bucket = _node; \
|
||||
} \
|
||||
\
|
||||
{ \
|
||||
FTC_Manager _manager = _cache->manager; \
|
||||
\
|
||||
\
|
||||
if ( _node != _manager->nodes_list ) \
|
||||
FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \
|
||||
(FTC_MruNode)_node ); \
|
||||
} \
|
||||
goto _Ok; \
|
||||
\
|
||||
_NewNode: \
|
||||
error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
|
||||
\
|
||||
_Ok: \
|
||||
*(FTC_Node*)&(node) = _node; \
|
||||
FT_END_STMNT |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, \
|
||||
(FTC_Node*)&(node) ); \
|
||||
FT_END_STMNT |
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCCACHE_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftccache.h */ |
||||
/* */ |
||||
/* FreeType internal cache interface (specification). */ |
||||
/* */ |
||||
/* Copyright 2000-2001, 2002, 2003, 2004 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCCACHE_H__ |
||||
#define __FTCCACHE_H__ |
||||
|
||||
|
||||
#include FT_CACHE_INTERNAL_MRU_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/* handle to cache object */ |
||||
typedef struct FTC_CacheRec_* FTC_Cache; |
||||
|
||||
/* handle to cache class */ |
||||
typedef const struct FTC_CacheClassRec_* FTC_CacheClass; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** CACHE NODE DEFINITIONS *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Each cache controls one or more cache nodes. Each node is part of */ |
||||
/* the global_lru list of the manager. Its `data' field however is used */ |
||||
/* as a reference count for now. */ |
||||
/* */ |
||||
/* A node can be anything, depending on the type of information held by */ |
||||
/* the cache. It can be an individual glyph image, a set of bitmaps */ |
||||
/* glyphs for a given size, some metrics, etc. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
/* structure size should be 20 bytes on 32-bits machines */ |
||||
typedef struct FTC_NodeRec_ |
||||
{ |
||||
FTC_MruNodeRec mru; /* circular mru list pointer */ |
||||
FTC_Node link; /* used for hashing */ |
||||
FT_UInt32 hash; /* used for hashing too */ |
||||
FT_UShort cache_index; /* index of cache the node belongs to */ |
||||
FT_Short ref_count; /* reference count for this node */ |
||||
|
||||
} FTC_NodeRec; |
||||
|
||||
|
||||
#define FTC_NODE( x ) ( (FTC_Node)(x) ) |
||||
#define FTC_NODE_P( x ) ( (FTC_Node*)(x) ) |
||||
|
||||
#define FTC_NODE__NEXT(x) FTC_NODE( (x)->mru.next ) |
||||
#define FTC_NODE__PREV(x) FTC_NODE( (x)->mru.prev ) |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* These functions are exported so that they can be called from */ |
||||
/* user-provided cache classes; otherwise, they are really part of the */ |
||||
/* cache sub-system internals. */ |
||||
/* */ |
||||
|
||||
/* reserved for manager's use */ |
||||
FT_EXPORT( void ) |
||||
ftc_node_destroy( FTC_Node node, |
||||
FTC_Manager manager ); |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/***** *****/ |
||||
/***** CACHE DEFINITIONS *****/ |
||||
/***** *****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
/* initialize a new cache node */ |
||||
typedef FT_Error |
||||
(*FTC_Node_NewFunc)( FTC_Node *pnode, |
||||
FT_Pointer query, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef FT_ULong |
||||
(*FTC_Node_WeightFunc)( FTC_Node node, |
||||
FTC_Cache cache ); |
||||
|
||||
/* compare a node to a given key pair */ |
||||
typedef FT_Bool |
||||
(*FTC_Node_CompareFunc)( FTC_Node node, |
||||
FT_Pointer key, |
||||
FTC_Cache cache ); |
||||
|
||||
|
||||
typedef void |
||||
(*FTC_Node_FreeFunc)( FTC_Node node, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_Cache_InitFunc)( FTC_Cache cache ); |
||||
|
||||
typedef void |
||||
(*FTC_Cache_DoneFunc)( FTC_Cache cache ); |
||||
|
||||
|
||||
typedef struct FTC_CacheClassRec_ |
||||
{ |
||||
FTC_Node_NewFunc node_new; |
||||
FTC_Node_WeightFunc node_weight; |
||||
FTC_Node_CompareFunc node_compare; |
||||
FTC_Node_CompareFunc node_remove_faceid; |
||||
FTC_Node_FreeFunc node_free; |
||||
|
||||
FT_UInt cache_size; |
||||
FTC_Cache_InitFunc cache_init; |
||||
FTC_Cache_DoneFunc cache_done; |
||||
|
||||
} FTC_CacheClassRec; |
||||
|
||||
|
||||
/* each cache really implements a dynamic hash table to manage its nodes */ |
||||
typedef struct FTC_CacheRec_ |
||||
{ |
||||
FT_UFast p; |
||||
FT_UFast mask; |
||||
FT_Long slack; |
||||
FTC_Node* buckets; |
||||
|
||||
FTC_CacheClassRec clazz; /* local copy, for speed */ |
||||
|
||||
FTC_Manager manager; |
||||
FT_Memory memory; |
||||
FT_UInt index; /* in manager's table */ |
||||
|
||||
FTC_CacheClass org_class; /* original class pointer */ |
||||
|
||||
} FTC_CacheRec; |
||||
|
||||
|
||||
#define FTC_CACHE( x ) ( (FTC_Cache)(x) ) |
||||
#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) ) |
||||
|
||||
|
||||
/* default cache initialize */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_Init( FTC_Cache cache ); |
||||
|
||||
/* default cache finalizer */ |
||||
FT_EXPORT( void ) |
||||
FTC_Cache_Done( FTC_Cache cache ); |
||||
|
||||
/* Call this function to lookup the cache. If no corresponding
|
||||
* node is found, a new one is automatically created. This function |
||||
* is capable of flushing the cache adequately to make room for the |
||||
* new cache object. |
||||
*/ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_Lookup( FTC_Cache cache, |
||||
FT_UInt32 hash, |
||||
FT_Pointer query, |
||||
FTC_Node *anode ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_Cache_NewNode( FTC_Cache cache, |
||||
FT_UInt32 hash, |
||||
FT_Pointer query, |
||||
FTC_Node *anode ); |
||||
|
||||
/* Remove all nodes that relate to a given face_id. This is useful
|
||||
* when un-installing fonts. Note that if a cache node relates to |
||||
* the face_id, but is locked (i.e., has 'ref_count > 0'), the node |
||||
* will _not_ be destroyed, but its internal face_id reference will |
||||
* be modified. |
||||
* |
||||
* The final result will be that the node will never come back |
||||
* in further lookup requests, and will be flushed on demand from |
||||
* the cache normally when its reference count reaches 0. |
||||
*/ |
||||
FT_EXPORT( void ) |
||||
FTC_Cache_RemoveFaceID( FTC_Cache cache, |
||||
FTC_FaceID face_id ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_Node *_bucket, *_pnode, _node; \
|
||||
FTC_Cache _cache = FTC_CACHE(cache); \
|
||||
FT_UInt32 _hash = (FT_UInt32)(hash); \
|
||||
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
|
||||
FT_UInt _idx; \
|
||||
\
|
||||
\
|
||||
error = 0; \
|
||||
_idx = _hash & _cache->mask; \
|
||||
if ( _idx < _cache->p ) \
|
||||
_idx = _hash & (_cache->mask*2 + 1); \
|
||||
\
|
||||
_bucket = _pnode = _cache->buckets + _idx; \
|
||||
for (;;) \
|
||||
{ \
|
||||
_node = *_pnode; \
|
||||
if ( _node == NULL ) \
|
||||
goto _NewNode; \
|
||||
\
|
||||
if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
|
||||
break; \
|
||||
\
|
||||
_pnode = &_node->link; \
|
||||
} \
|
||||
\
|
||||
if ( _node != *_bucket ) \
|
||||
{ \
|
||||
*_pnode = _node->link; \
|
||||
_node->link = *_bucket; \
|
||||
*_bucket = _node; \
|
||||
} \
|
||||
\
|
||||
{ \
|
||||
FTC_Manager _manager = _cache->manager; \
|
||||
\
|
||||
\
|
||||
if ( _node != _manager->nodes_list ) \
|
||||
FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \
|
||||
(FTC_MruNode)_node ); \
|
||||
} \
|
||||
goto _Ok; \
|
||||
\
|
||||
_NewNode: \
|
||||
error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \
|
||||
\
|
||||
_Ok: \
|
||||
*(FTC_Node*)&(node) = _node; \
|
||||
FT_END_STMNT |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, \
|
||||
(FTC_Node*)&(node) ); \
|
||||
FT_END_STMNT |
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCCACHE_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
|
@ -1,297 +1,297 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcglyph.h */ |
||||
/* */ |
||||
/* FreeType abstract glyph cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000-2001, 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* |
||||
* FTC_GCache is an _abstract_ cache object optimized to store glyph |
||||
* data. It works as follows: |
||||
* |
||||
* - It manages FTC_GNode objects. Each one of them can hold one or more |
||||
* glyph `items'. Item types are not specified in the FTC_GCache but |
||||
* in classes that extend it. |
||||
* |
||||
* - Glyph attributes, like face ID, character size, render mode, etc., |
||||
* can be grouped into abstract `glyph families'. This avoids storing |
||||
* the attributes within the FTC_GCache, since it is likely that many |
||||
* FTC_GNodes will belong to the same family in typical uses. |
||||
* |
||||
* - Each FTC_GNode is thus an FTC_Node with two additional fields: |
||||
* |
||||
* * gindex: A glyph index, or the first index in a glyph range. |
||||
* * family: A pointer to a glyph `family'. |
||||
* |
||||
* - Family types are not fully specific in the FTC_Family type, but |
||||
* by classes that extend it. |
||||
* |
||||
* Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache. |
||||
* They share an FTC_Family sub-class called FTC_BasicFamily which is |
||||
* used to store the following data: face ID, pixel/point sizes, load |
||||
* flags. For more details see the file `src/cache/ftcbasic.c'. |
||||
* |
||||
* Client applications can extend FTC_GNode with their own FTC_GNode |
||||
* and FTC_Family sub-classes to implement more complex caches (e.g., |
||||
* handling automatic synthesis, like obliquing & emboldening, colored |
||||
* glyphs, etc.). |
||||
* |
||||
* See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and |
||||
* `ftcsbits.h', which both extend FTC_GCache with additional |
||||
* optimizations. |
||||
* |
||||
* A typical FTC_GCache implementation must provide at least the |
||||
* following: |
||||
* |
||||
* - FTC_GNode sub-class, e.g. MyNode, with relevant methods: |
||||
* my_node_new (must call FTC_GNode_Init) |
||||
* my_node_free (must call FTC_GNode_Done) |
||||
* my_node_compare (must call FTC_GNode_Compare) |
||||
* my_node_remove_faceid (must call ftc_gnode_unselect in case |
||||
* of match) |
||||
* |
||||
* - FTC_Family sub-class, e.g. MyFamily, with relevant methods: |
||||
* my_family_compare |
||||
* my_family_init |
||||
* my_family_reset (optional) |
||||
* my_family_done |
||||
* |
||||
* - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query |
||||
* data. |
||||
* |
||||
* - Constant structures for a FTC_GNodeClass. |
||||
* |
||||
* - MyCacheNew() can be implemented easily as a call to the convenience |
||||
* function FTC_GCache_New. |
||||
* |
||||
* - MyCacheLookup with a call to FTC_GCache_Lookup. This function will |
||||
* automatically: |
||||
* |
||||
* - Search for the corresponding family in the cache, or create |
||||
* a new one if necessary. Put it in FTC_GQUERY(myquery).family |
||||
* |
||||
* - Call FTC_Cache_Lookup. |
||||
* |
||||
* If it returns NULL, you should create a new node, then call |
||||
* ftc_cache_add as usual. |
||||
*/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Important: The functions defined in this file are only used to */ |
||||
/* implement an abstract glyph cache class. You need to */ |
||||
/* provide additional logic to implement a complete cache. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/********* *********/ |
||||
/********* WARNING, THIS IS BETA CODE. *********/ |
||||
/********* *********/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCGLYPH_H__ |
||||
#define __FTCGLYPH_H__ |
||||
|
||||
|
||||
#include <ft2build.h> |
||||
#include FT_CACHE_INTERNAL_MANAGER_H |
||||
|
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
|
||||
/*
|
||||
* We can group glyphs into `families'. Each family correspond to a |
||||
* given face ID, character size, transform, etc. |
||||
* |
||||
* Families are implemented as MRU list nodes. They are |
||||
* reference-counted. |
||||
*/ |
||||
|
||||
typedef struct FTC_FamilyRec_ |
||||
{ |
||||
FTC_MruNodeRec mrunode; |
||||
FT_UInt num_nodes; /* current number of nodes in this family */ |
||||
FTC_Cache cache; |
||||
FTC_MruListClass clazz; |
||||
|
||||
} FTC_FamilyRec, *FTC_Family; |
||||
|
||||
#define FTC_FAMILY(x) ( (FTC_Family)(x) ) |
||||
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) |
||||
|
||||
|
||||
typedef struct FTC_GNodeRec_ |
||||
{ |
||||
FTC_NodeRec node; |
||||
FTC_Family family; |
||||
FT_UInt gindex; |
||||
|
||||
} FTC_GNodeRec, *FTC_GNode; |
||||
|
||||
#define FTC_GNODE( x ) ( (FTC_GNode)(x) ) |
||||
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) ) |
||||
|
||||
|
||||
typedef struct FTC_GQueryRec_ |
||||
{ |
||||
FT_UInt gindex; |
||||
FTC_Family family; |
||||
|
||||
} FTC_GQueryRec, *FTC_GQuery; |
||||
|
||||
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) ) |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* These functions are exported so that they can be called from */ |
||||
/* user-provided cache classes; otherwise, they are really part of the */ |
||||
/* cache sub-system internals. */ |
||||
/* */ |
||||
|
||||
/* must be called by derived FTC_Node_InitFunc routines */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_Init( FTC_GNode node, |
||||
FT_UInt gindex, /* glyph index for node */ |
||||
FTC_Family family ); |
||||
|
||||
/* returns TRUE iff the query's glyph index correspond to the node; */ |
||||
/* this assumes that the "family" and "hash" fields of the query are */ |
||||
/* already correctly set */ |
||||
FT_EXPORT( FT_Bool ) |
||||
FTC_GNode_Compare( FTC_GNode gnode, |
||||
FTC_GQuery gquery ); |
||||
|
||||
/* call this function to clear a node's family -- this is necessary */ |
||||
/* to implement the `node_remove_faceid' cache method correctly */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode, |
||||
FTC_Cache cache ); |
||||
|
||||
/* must be called by derived FTC_Node_DoneFunc routines */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_Done( FTC_GNode node, |
||||
FTC_Cache cache ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_Family_Init( FTC_Family family, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef struct FTC_GCacheRec_ |
||||
{ |
||||
FTC_CacheRec cache; |
||||
FTC_MruListRec families; |
||||
|
||||
} FTC_GCacheRec, *FTC_GCache; |
||||
|
||||
#define FTC_GCACHE( x ) ((FTC_GCache)(x)) |
||||
|
||||
|
||||
/* can be used as @FTC_Cache_InitFunc */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_Init( FTC_GCache cache ); |
||||
|
||||
|
||||
/* can be used as @FTC_Cache_DoneFunc */ |
||||
FT_EXPORT( void ) |
||||
FTC_GCache_Done( FTC_GCache cache ); |
||||
|
||||
|
||||
/* the glyph cache class adds fields for the family implementation */ |
||||
typedef struct FTC_GCacheClassRec_ |
||||
{ |
||||
FTC_CacheClassRec clazz; |
||||
FTC_MruListClass family_class; |
||||
|
||||
} FTC_GCacheClassRec; |
||||
|
||||
typedef const FTC_GCacheClassRec* FTC_GCacheClass; |
||||
|
||||
#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) |
||||
|
||||
#define FTC_CACHE__GCACHE_CLASS( x ) \ |
||||
FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) |
||||
#define FTC_CACHE__FAMILY_CLASS( x ) \ |
||||
((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_class) |
||||
|
||||
|
||||
/* convenience function; use it instead of FTC_Manager_Register_Cache */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_New( FTC_Manager manager, |
||||
FTC_GCacheClass clazz, |
||||
FTC_GCache *acache ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_Lookup( FTC_GCache cache, |
||||
FT_UInt32 hash, |
||||
FT_UInt gindex, |
||||
FTC_GQuery query, |
||||
FTC_Node *anode ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
||||
gindex, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_GCache _gcache = FTC_GCACHE( cache ); \
|
||||
FTC_GQuery _gquery = (FTC_GQuery)( query ); \
|
||||
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
|
||||
\
|
||||
\
|
||||
_gquery->gindex = (gindex); \
|
||||
\
|
||||
FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \
|
||||
_gquery->family, error ); \
|
||||
if ( !error ) \
|
||||
{ \
|
||||
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
|
||||
} \
|
||||
FT_END_STMNT |
||||
/* */ |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
||||
gindex, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE(cache), hash, gindex, FTC_GQUERY(query), \
|
||||
(FTC_Node*) &(node) ); \
|
||||
FT_END_STMNT |
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCGLYPH_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcglyph.h */ |
||||
/* */ |
||||
/* FreeType abstract glyph cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000-2001, 2003, 2004 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
/*
|
||||
* |
||||
* FTC_GCache is an _abstract_ cache object optimized to store glyph |
||||
* data. It works as follows: |
||||
* |
||||
* - It manages FTC_GNode objects. Each one of them can hold one or more |
||||
* glyph `items'. Item types are not specified in the FTC_GCache but |
||||
* in classes that extend it. |
||||
* |
||||
* - Glyph attributes, like face ID, character size, render mode, etc., |
||||
* can be grouped into abstract `glyph families'. This avoids storing |
||||
* the attributes within the FTC_GCache, since it is likely that many |
||||
* FTC_GNodes will belong to the same family in typical uses. |
||||
* |
||||
* - Each FTC_GNode is thus an FTC_Node with two additional fields: |
||||
* |
||||
* * gindex: A glyph index, or the first index in a glyph range. |
||||
* * family: A pointer to a glyph `family'. |
||||
* |
||||
* - Family types are not fully specific in the FTC_Family type, but |
||||
* by classes that extend it. |
||||
* |
||||
* Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache. |
||||
* They share an FTC_Family sub-class called FTC_BasicFamily which is |
||||
* used to store the following data: face ID, pixel/point sizes, load |
||||
* flags. For more details see the file `src/cache/ftcbasic.c'. |
||||
* |
||||
* Client applications can extend FTC_GNode with their own FTC_GNode |
||||
* and FTC_Family sub-classes to implement more complex caches (e.g., |
||||
* handling automatic synthesis, like obliquing & emboldening, colored |
||||
* glyphs, etc.). |
||||
* |
||||
* See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and |
||||
* `ftcsbits.h', which both extend FTC_GCache with additional |
||||
* optimizations. |
||||
* |
||||
* A typical FTC_GCache implementation must provide at least the |
||||
* following: |
||||
* |
||||
* - FTC_GNode sub-class, e.g. MyNode, with relevant methods: |
||||
* my_node_new (must call FTC_GNode_Init) |
||||
* my_node_free (must call FTC_GNode_Done) |
||||
* my_node_compare (must call FTC_GNode_Compare) |
||||
* my_node_remove_faceid (must call ftc_gnode_unselect in case |
||||
* of match) |
||||
* |
||||
* - FTC_Family sub-class, e.g. MyFamily, with relevant methods: |
||||
* my_family_compare |
||||
* my_family_init |
||||
* my_family_reset (optional) |
||||
* my_family_done |
||||
* |
||||
* - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query |
||||
* data. |
||||
* |
||||
* - Constant structures for a FTC_GNodeClass. |
||||
* |
||||
* - MyCacheNew() can be implemented easily as a call to the convenience |
||||
* function FTC_GCache_New. |
||||
* |
||||
* - MyCacheLookup with a call to FTC_GCache_Lookup. This function will |
||||
* automatically: |
||||
* |
||||
* - Search for the corresponding family in the cache, or create |
||||
* a new one if necessary. Put it in FTC_GQUERY(myquery).family |
||||
* |
||||
* - Call FTC_Cache_Lookup. |
||||
* |
||||
* If it returns NULL, you should create a new node, then call |
||||
* ftc_cache_add as usual. |
||||
*/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Important: The functions defined in this file are only used to */ |
||||
/* implement an abstract glyph cache class. You need to */ |
||||
/* provide additional logic to implement a complete cache. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/********* *********/ |
||||
/********* WARNING, THIS IS BETA CODE. *********/ |
||||
/********* *********/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCGLYPH_H__ |
||||
#define __FTCGLYPH_H__ |
||||
|
||||
|
||||
#include <ft2build.h> |
||||
#include FT_CACHE_INTERNAL_MANAGER_H |
||||
|
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
|
||||
/*
|
||||
* We can group glyphs into `families'. Each family correspond to a |
||||
* given face ID, character size, transform, etc. |
||||
* |
||||
* Families are implemented as MRU list nodes. They are |
||||
* reference-counted. |
||||
*/ |
||||
|
||||
typedef struct FTC_FamilyRec_ |
||||
{ |
||||
FTC_MruNodeRec mrunode; |
||||
FT_UInt num_nodes; /* current number of nodes in this family */ |
||||
FTC_Cache cache; |
||||
FTC_MruListClass clazz; |
||||
|
||||
} FTC_FamilyRec, *FTC_Family; |
||||
|
||||
#define FTC_FAMILY(x) ( (FTC_Family)(x) ) |
||||
#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) |
||||
|
||||
|
||||
typedef struct FTC_GNodeRec_ |
||||
{ |
||||
FTC_NodeRec node; |
||||
FTC_Family family; |
||||
FT_UInt gindex; |
||||
|
||||
} FTC_GNodeRec, *FTC_GNode; |
||||
|
||||
#define FTC_GNODE( x ) ( (FTC_GNode)(x) ) |
||||
#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) ) |
||||
|
||||
|
||||
typedef struct FTC_GQueryRec_ |
||||
{ |
||||
FT_UInt gindex; |
||||
FTC_Family family; |
||||
|
||||
} FTC_GQueryRec, *FTC_GQuery; |
||||
|
||||
#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) ) |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* These functions are exported so that they can be called from */ |
||||
/* user-provided cache classes; otherwise, they are really part of the */ |
||||
/* cache sub-system internals. */ |
||||
/* */ |
||||
|
||||
/* must be called by derived FTC_Node_InitFunc routines */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_Init( FTC_GNode node, |
||||
FT_UInt gindex, /* glyph index for node */ |
||||
FTC_Family family ); |
||||
|
||||
/* returns TRUE iff the query's glyph index correspond to the node; */ |
||||
/* this assumes that the "family" and "hash" fields of the query are */ |
||||
/* already correctly set */ |
||||
FT_EXPORT( FT_Bool ) |
||||
FTC_GNode_Compare( FTC_GNode gnode, |
||||
FTC_GQuery gquery ); |
||||
|
||||
/* call this function to clear a node's family -- this is necessary */ |
||||
/* to implement the `node_remove_faceid' cache method correctly */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_UnselectFamily( FTC_GNode gnode, |
||||
FTC_Cache cache ); |
||||
|
||||
/* must be called by derived FTC_Node_DoneFunc routines */ |
||||
FT_EXPORT( void ) |
||||
FTC_GNode_Done( FTC_GNode node, |
||||
FTC_Cache cache ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_Family_Init( FTC_Family family, |
||||
FTC_Cache cache ); |
||||
|
||||
typedef struct FTC_GCacheRec_ |
||||
{ |
||||
FTC_CacheRec cache; |
||||
FTC_MruListRec families; |
||||
|
||||
} FTC_GCacheRec, *FTC_GCache; |
||||
|
||||
#define FTC_GCACHE( x ) ((FTC_GCache)(x)) |
||||
|
||||
|
||||
/* can be used as @FTC_Cache_InitFunc */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_Init( FTC_GCache cache ); |
||||
|
||||
|
||||
/* can be used as @FTC_Cache_DoneFunc */ |
||||
FT_EXPORT( void ) |
||||
FTC_GCache_Done( FTC_GCache cache ); |
||||
|
||||
|
||||
/* the glyph cache class adds fields for the family implementation */ |
||||
typedef struct FTC_GCacheClassRec_ |
||||
{ |
||||
FTC_CacheClassRec clazz; |
||||
FTC_MruListClass family_class; |
||||
|
||||
} FTC_GCacheClassRec; |
||||
|
||||
typedef const FTC_GCacheClassRec* FTC_GCacheClass; |
||||
|
||||
#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) |
||||
|
||||
#define FTC_CACHE__GCACHE_CLASS( x ) \ |
||||
FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) |
||||
#define FTC_CACHE__FAMILY_CLASS( x ) \ |
||||
((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_class) |
||||
|
||||
|
||||
/* convenience function; use it instead of FTC_Manager_Register_Cache */ |
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_New( FTC_Manager manager, |
||||
FTC_GCacheClass clazz, |
||||
FTC_GCache *acache ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_GCache_Lookup( FTC_GCache cache, |
||||
FT_UInt32 hash, |
||||
FT_UInt gindex, |
||||
FTC_GQuery query, |
||||
FTC_Node *anode ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
||||
gindex, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FTC_GCache _gcache = FTC_GCACHE( cache ); \
|
||||
FTC_GQuery _gquery = (FTC_GQuery)( query ); \
|
||||
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
|
||||
\
|
||||
\
|
||||
_gquery->gindex = (gindex); \
|
||||
\
|
||||
FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \
|
||||
_gquery->family, error ); \
|
||||
if ( !error ) \
|
||||
{ \
|
||||
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
|
||||
} \
|
||||
FT_END_STMNT |
||||
/* */ |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ |
||||
gindex, query, node, error ) \
|
||||
FT_BEGIN_STMNT \
|
||||
error = FTC_GCache_Lookup( FTC_GCACHE(cache), hash, gindex, FTC_GQUERY(query), \
|
||||
(FTC_Node*) &(node) ); \
|
||||
FT_END_STMNT |
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCGLYPH_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
|
@ -1,246 +1,246 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcmru.h */ |
||||
/* */ |
||||
/* Simple MRU list-cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000-2001, 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* An MRU is a list that cannot hold more than a certain number of */ |
||||
/* elements (`max_elements'). All elements in the list are sorted in */ |
||||
/* least-recently-used order, i.e., the `oldest' element is at the tail */ |
||||
/* of the list. */ |
||||
/* */ |
||||
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */ |
||||
/* the list is searched for an element with the corresponding key. If */ |
||||
/* it is found, the element is moved to the head of the list and is */ |
||||
/* returned. */ |
||||
/* */ |
||||
/* If no corresponding element is found, the lookup routine will try to */ |
||||
/* obtain a new element with the relevant key. If the list is already */ |
||||
/* full, the oldest element from the list is discarded and replaced by a */ |
||||
/* new one; a new element is added to the list otherwise. */ |
||||
/* */ |
||||
/* Note that it is possible to pre-allocate the element list nodes. */ |
||||
/* This is handy if `max_elements' is sufficiently small, as it saves */ |
||||
/* allocations/releases during the lookup process. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCMRU_H__ |
||||
#define __FTCMRU_H__ |
||||
|
||||
|
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
|
||||
#ifdef FREETYPE_H |
||||
#error "freetype.h of FreeType 1 has been loaded!" |
||||
#error "Please fix the directory search order for header files" |
||||
#error "so that freetype.h of FreeType 2 is found first." |
||||
#endif |
||||
|
||||
#define xxFT_DEBUG_ERROR |
||||
#define FTC_INLINE |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct FTC_MruNodeRec_* FTC_MruNode; |
||||
|
||||
typedef struct FTC_MruNodeRec_ |
||||
{ |
||||
FTC_MruNode next; |
||||
FTC_MruNode prev; |
||||
|
||||
} FTC_MruNodeRec; |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Prepend( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Up( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Remove( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
|
||||
typedef struct FTC_MruListRec_* FTC_MruList; |
||||
|
||||
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass; |
||||
|
||||
|
||||
typedef FT_Int |
||||
(*FTC_MruNode_CompareFunc)( FTC_MruNode node, |
||||
FT_Pointer key ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_MruNode_InitFunc)( FTC_MruNode node, |
||||
FT_Pointer key, |
||||
FT_Pointer data ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_MruNode_ResetFunc)( FTC_MruNode node, |
||||
FT_Pointer key, |
||||
FT_Pointer data ); |
||||
|
||||
typedef void |
||||
(*FTC_MruNode_DoneFunc)( FTC_MruNode node, |
||||
FT_Pointer data ); |
||||
|
||||
|
||||
typedef struct FTC_MruListClassRec_ |
||||
{ |
||||
FT_UInt node_size; |
||||
FTC_MruNode_CompareFunc node_compare; |
||||
FTC_MruNode_InitFunc node_init; |
||||
FTC_MruNode_ResetFunc node_reset; |
||||
FTC_MruNode_DoneFunc node_done; |
||||
|
||||
} FTC_MruListClassRec; |
||||
|
||||
typedef struct FTC_MruListRec_ |
||||
{ |
||||
FT_UInt num_nodes; |
||||
FT_UInt max_nodes; |
||||
FTC_MruNode nodes; |
||||
FT_Pointer data; |
||||
FTC_MruListClassRec clazz; |
||||
FT_Memory memory; |
||||
|
||||
} FTC_MruListRec; |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Init( FTC_MruList list, |
||||
FTC_MruListClass clazz, |
||||
FT_UInt max_nodes, |
||||
FT_Pointer data, |
||||
FT_Memory memory ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Reset( FTC_MruList list ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Done( FTC_MruList list ); |
||||
|
||||
FT_EXPORT( FTC_MruNode ) |
||||
FTC_MruList_Find( FTC_MruList list, |
||||
FT_Pointer key ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_MruList_New( FTC_MruList list, |
||||
FT_Pointer key, |
||||
FTC_MruNode *anode ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_MruList_Lookup( FTC_MruList list, |
||||
FT_Pointer key, |
||||
FTC_MruNode *pnode ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Remove( FTC_MruList list, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_RemoveSelection( FTC_MruList list, |
||||
FTC_MruNode_CompareFunc selection, |
||||
FT_Pointer key ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode* _pfirst = &(list)->nodes; \
|
||||
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
|
||||
FTC_MruNode _first, _node; \
|
||||
\
|
||||
\
|
||||
error = 0; \
|
||||
_first = *(_pfirst); \
|
||||
_node = NULL; \
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
_node = _first; \
|
||||
do \
|
||||
{ \
|
||||
if ( _compare( _node, (key) ) ) \
|
||||
{ \
|
||||
if ( _node != _first ) \
|
||||
FTC_MruNode_Up( _pfirst, _node ); \
|
||||
\
|
||||
*(FTC_MruNode*)&(node) = _node; \
|
||||
goto _MruOk; \
|
||||
} \
|
||||
_node = _node->next; \
|
||||
\
|
||||
} while ( _node != _first) ; \
|
||||
} \
|
||||
\
|
||||
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \
|
||||
_MruOk: \
|
||||
; \
|
||||
FT_END_STMNT |
||||
|
||||
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
||||
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error ) |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
||||
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
|
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP( list, node ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode _first = (list)->nodes; \
|
||||
\
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
FTC_MruNode _node = _first; \
|
||||
\
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
*(FTC_MruNode*)&(node) = _node; |
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP_END() \ |
||||
_node = _node->next; \
|
||||
\
|
||||
} while ( _node != _first ); \
|
||||
} \
|
||||
FT_END_STMNT |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCMRU_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* ftcmru.h */ |
||||
/* */ |
||||
/* Simple MRU list-cache (specification). */ |
||||
/* */ |
||||
/* Copyright 2000-2001, 2003, 2004 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* An MRU is a list that cannot hold more than a certain number of */ |
||||
/* elements (`max_elements'). All elements in the list are sorted in */ |
||||
/* least-recently-used order, i.e., the `oldest' element is at the tail */ |
||||
/* of the list. */ |
||||
/* */ |
||||
/* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */ |
||||
/* the list is searched for an element with the corresponding key. If */ |
||||
/* it is found, the element is moved to the head of the list and is */ |
||||
/* returned. */ |
||||
/* */ |
||||
/* If no corresponding element is found, the lookup routine will try to */ |
||||
/* obtain a new element with the relevant key. If the list is already */ |
||||
/* full, the oldest element from the list is discarded and replaced by a */ |
||||
/* new one; a new element is added to the list otherwise. */ |
||||
/* */ |
||||
/* Note that it is possible to pre-allocate the element list nodes. */ |
||||
/* This is handy if `max_elements' is sufficiently small, as it saves */ |
||||
/* allocations/releases during the lookup process. */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#ifndef __FTCMRU_H__ |
||||
#define __FTCMRU_H__ |
||||
|
||||
|
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
|
||||
#ifdef FREETYPE_H |
||||
#error "freetype.h of FreeType 1 has been loaded!" |
||||
#error "Please fix the directory search order for header files" |
||||
#error "so that freetype.h of FreeType 2 is found first." |
||||
#endif |
||||
|
||||
#define xxFT_DEBUG_ERROR |
||||
#define FTC_INLINE |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct FTC_MruNodeRec_* FTC_MruNode; |
||||
|
||||
typedef struct FTC_MruNodeRec_ |
||||
{ |
||||
FTC_MruNode next; |
||||
FTC_MruNode prev; |
||||
|
||||
} FTC_MruNodeRec; |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Prepend( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Up( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruNode_Remove( FTC_MruNode *plist, |
||||
FTC_MruNode node ); |
||||
|
||||
|
||||
typedef struct FTC_MruListRec_* FTC_MruList; |
||||
|
||||
typedef struct FTC_MruListClassRec_ const * FTC_MruListClass; |
||||
|
||||
|
||||
typedef FT_Int |
||||
(*FTC_MruNode_CompareFunc)( FTC_MruNode node, |
||||
FT_Pointer key ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_MruNode_InitFunc)( FTC_MruNode node, |
||||
FT_Pointer key, |
||||
FT_Pointer data ); |
||||
|
||||
typedef FT_Error |
||||
(*FTC_MruNode_ResetFunc)( FTC_MruNode node, |
||||
FT_Pointer key, |
||||
FT_Pointer data ); |
||||
|
||||
typedef void |
||||
(*FTC_MruNode_DoneFunc)( FTC_MruNode node, |
||||
FT_Pointer data ); |
||||
|
||||
|
||||
typedef struct FTC_MruListClassRec_ |
||||
{ |
||||
FT_UInt node_size; |
||||
FTC_MruNode_CompareFunc node_compare; |
||||
FTC_MruNode_InitFunc node_init; |
||||
FTC_MruNode_ResetFunc node_reset; |
||||
FTC_MruNode_DoneFunc node_done; |
||||
|
||||
} FTC_MruListClassRec; |
||||
|
||||
typedef struct FTC_MruListRec_ |
||||
{ |
||||
FT_UInt num_nodes; |
||||
FT_UInt max_nodes; |
||||
FTC_MruNode nodes; |
||||
FT_Pointer data; |
||||
FTC_MruListClassRec clazz; |
||||
FT_Memory memory; |
||||
|
||||
} FTC_MruListRec; |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Init( FTC_MruList list, |
||||
FTC_MruListClass clazz, |
||||
FT_UInt max_nodes, |
||||
FT_Pointer data, |
||||
FT_Memory memory ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Reset( FTC_MruList list ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Done( FTC_MruList list ); |
||||
|
||||
FT_EXPORT( FTC_MruNode ) |
||||
FTC_MruList_Find( FTC_MruList list, |
||||
FT_Pointer key ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_MruList_New( FTC_MruList list, |
||||
FT_Pointer key, |
||||
FTC_MruNode *anode ); |
||||
|
||||
FT_EXPORT( FT_Error ) |
||||
FTC_MruList_Lookup( FTC_MruList list, |
||||
FT_Pointer key, |
||||
FTC_MruNode *pnode ); |
||||
|
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_Remove( FTC_MruList list, |
||||
FTC_MruNode node ); |
||||
|
||||
FT_EXPORT( void ) |
||||
FTC_MruList_RemoveSelection( FTC_MruList list, |
||||
FTC_MruNode_CompareFunc selection, |
||||
FT_Pointer key ); |
||||
|
||||
|
||||
#ifdef FTC_INLINE |
||||
|
||||
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode* _pfirst = &(list)->nodes; \
|
||||
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
|
||||
FTC_MruNode _first, _node; \
|
||||
\
|
||||
\
|
||||
error = 0; \
|
||||
_first = *(_pfirst); \
|
||||
_node = NULL; \
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
_node = _first; \
|
||||
do \
|
||||
{ \
|
||||
if ( _compare( _node, (key) ) ) \
|
||||
{ \
|
||||
if ( _node != _first ) \
|
||||
FTC_MruNode_Up( _pfirst, _node ); \
|
||||
\
|
||||
*(FTC_MruNode*)&(node) = _node; \
|
||||
goto _MruOk; \
|
||||
} \
|
||||
_node = _node->next; \
|
||||
\
|
||||
} while ( _node != _first) ; \
|
||||
} \
|
||||
\
|
||||
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \
|
||||
_MruOk: \
|
||||
; \
|
||||
FT_END_STMNT |
||||
|
||||
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
||||
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error ) |
||||
|
||||
#else /* !FTC_INLINE */ |
||||
|
||||
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ |
||||
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
|
||||
|
||||
#endif /* !FTC_INLINE */ |
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP( list, node ) \ |
||||
FT_BEGIN_STMNT \
|
||||
FTC_MruNode _first = (list)->nodes; \
|
||||
\
|
||||
\
|
||||
if ( _first ) \
|
||||
{ \
|
||||
FTC_MruNode _node = _first; \
|
||||
\
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
*(FTC_MruNode*)&(node) = _node; |
||||
|
||||
|
||||
#define FTC_MRULIST_LOOP_END() \ |
||||
_node = _node->next; \
|
||||
\
|
||||
} while ( _node != _first ); \
|
||||
} \
|
||||
FT_END_STMNT |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
|
||||
#endif /* __FTCMRU_H__ */ |
||||
|
||||
|
||||
/* END */ |
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,431 +1,431 @@ |
||||
#include "afloader.h" |
||||
#include "afhints.h" |
||||
#include "afglobal.h" |
||||
#include "aflatin.h" |
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_init( AF_Loader loader, |
||||
FT_Memory memory ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
FT_ZERO( loader ); |
||||
|
||||
af_glyph_hints_init( &loader->hints, memory ); |
||||
|
||||
error = FT_GlyphLoader_New( memory, &loader->gloader ); |
||||
if ( !error ) |
||||
{ |
||||
error = FT_GlyphLoader_CreateExtra( loader->gloader ); |
||||
if ( error ) |
||||
{ |
||||
FT_GlyphLoader_Done( loader->gloader ); |
||||
loader->gloader = NULL; |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_reset( AF_Loader loader, |
||||
FT_Face face ) |
||||
{ |
||||
FT_Error error = 0; |
||||
|
||||
loader->face = face; |
||||
loader->gloader = face->glyph->internal->loader; |
||||
loader->globals = (AF_FaceGlobals) face->autohint.data; |
||||
|
||||
if ( loader->globals == NULL ) |
||||
{ |
||||
error = af_face_globals_new( face, &loader->globals ); |
||||
if ( !error ) |
||||
{ |
||||
face->autohint.data = (FT_Pointer) loader->globals; |
||||
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free; |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( void ) |
||||
af_loader_done( AF_Loader loader ) |
||||
{ |
||||
loader->face = NULL; |
||||
loader->globals = NULL; |
||||
|
||||
FT_GlyphLoader_Done( loader->gloader ); |
||||
loader->gloader = NULL; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
af_loader_load_g( AF_Loader loader, |
||||
AF_Scaler scaler, |
||||
FT_UInt glyph_index, |
||||
FT_Int32 load_flags, |
||||
FT_UInt depth ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Face face = loader->face; |
||||
AF_FaceGlobals globals = loader->globals; |
||||
FT_GlyphLoader gloader = loader->gloader; |
||||
AF_ScriptMetrics metrics = loader->metrics; |
||||
AF_GlyphHints hints = &loader->hints; |
||||
FT_GlyphSlot slot = face->glyph; |
||||
FT_Slot_Internal internal = slot->internal; |
||||
|
||||
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
loader->transformed = internal->glyph_transformed; |
||||
if ( loader->transformed ) |
||||
{ |
||||
FT_Matrix inverse; |
||||
|
||||
loader->trans_matrix = internal->glyph_matrix; |
||||
loader->trans_delta = internal->glyph_delta; |
||||
|
||||
inverse = loader->trans_matrix; |
||||
FT_Matrix_Invert( &inverse ); |
||||
FT_Vector_Transform( &loader->trans_delta, &inverse ); |
||||
} |
||||
|
||||
/* set linear metrics */ |
||||
slot->linearHoriAdvance = slot->metrics.horiAdvance; |
||||
slot->linearVertAdvance = slot->metrics.vertAdvance; |
||||
|
||||
switch ( slot->format ) |
||||
{ |
||||
case FT_GLYPH_FORMAT_OUTLINE: |
||||
/* translate the loaded glyph when an internal transform
|
||||
* is needed |
||||
*/ |
||||
if ( loader->transformed ) |
||||
{ |
||||
FT_Vector* point = slot->outline.points; |
||||
FT_Vector* limit = point + slot->outline.n_points; |
||||
|
||||
for ( ; point < limit; point++ ) |
||||
{ |
||||
point->x += loader->trans_delta.x; |
||||
point->y += loader->trans_delta.y; |
||||
} |
||||
} |
||||
|
||||
/* copy the outline points in the loader's current */ |
||||
/* extra points which is used to keep original glyph coordinates */ |
||||
error = FT_GlyphLoader_CheckPoints( gloader, |
||||
slot->outline.n_points + 2, |
||||
slot->outline.n_contours ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
FT_ARRAY_COPY( gloader->current.extra_points, |
||||
slot->outline.points, |
||||
slot->outline.n_points ); |
||||
|
||||
FT_ARRAY_COPY( gloader->current.outline.contours, |
||||
slot->outline.contours, |
||||
slot->outline.n_contours ); |
||||
|
||||
FT_ARRAY_COPY( gloader->current.outline.tags, |
||||
slot->outline.tags, |
||||
slot->outline.n_points ); |
||||
|
||||
gloader->current.outline.n_points = slot->outline.n_points; |
||||
gloader->current.outline.n_contours = slot->outline.n_contours; |
||||
|
||||
/* compute original phantom points */ |
||||
loader->pp1.x = hints->x_delta; |
||||
loader->pp1.y = hints->y_delta; |
||||
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, |
||||
hints->x_scale ) + hints->x_delta; |
||||
loader->pp2.y = hints->y_delta; |
||||
|
||||
/* be sure to check for spacing glyphs */ |
||||
if ( slot->outline.n_points == 0 ) |
||||
goto Hint_Metrics; |
||||
|
||||
/* now load the slot image into the auto-outline and run the */ |
||||
/* automatic hinting process */ |
||||
error = metrics->clazz->script_hints_init( hints, |
||||
&gloader->current.outline, |
||||
metrics ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* apply the hints */ |
||||
metrics->clazz->script_hints_apply( hints, |
||||
&gloader->current.outline, |
||||
metrics ); |
||||
/* we now need to hint the metrics according to the change in */ |
||||
/* width/positioning that occured during the hinting process */ |
||||
{ |
||||
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
||||
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ]; |
||||
AF_Edge edge1 = axis->edges; /* leftmost edge */ |
||||
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */ |
||||
|
||||
|
||||
old_advance = loader->pp2.x; |
||||
old_rsb = old_advance - edge2->opos; |
||||
old_lsb = edge1->opos; |
||||
new_lsb = edge1->pos; |
||||
|
||||
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb ); |
||||
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb ); |
||||
|
||||
#if 0 |
||||
/* try to fix certain bad advance computations */ |
||||
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 ) |
||||
loader->pp2.x += 64; |
||||
#endif |
||||
} |
||||
|
||||
/* good, we simply add the glyph to our loader's base */ |
||||
FT_GlyphLoader_Add( gloader ); |
||||
break; |
||||
|
||||
case FT_GLYPH_FORMAT_COMPOSITE: |
||||
{ |
||||
FT_UInt nn, num_subglyphs = slot->num_subglyphs; |
||||
FT_UInt num_base_subgs, start_point; |
||||
FT_SubGlyph subglyph; |
||||
|
||||
|
||||
start_point = gloader->base.outline.n_points; |
||||
|
||||
/* first of all, copy the subglyph descriptors in the glyph loader */ |
||||
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
FT_ARRAY_COPY( gloader->current.subglyphs, |
||||
slot->subglyphs, |
||||
num_subglyphs ); |
||||
|
||||
gloader->current.num_subglyphs = num_subglyphs; |
||||
num_base_subgs = gloader->base.num_subglyphs; |
||||
|
||||
/* now, read each subglyph independently */ |
||||
for ( nn = 0; nn < num_subglyphs; nn++ ) |
||||
{ |
||||
FT_Vector pp1, pp2; |
||||
FT_Pos x, y; |
||||
FT_UInt num_points, num_new_points, num_base_points; |
||||
|
||||
|
||||
/* gloader.current.subglyphs can change during glyph loading due */ |
||||
/* to re-allocation -- we must recompute the current subglyph on */ |
||||
/* each iteration */ |
||||
subglyph = gloader->base.subglyphs + num_base_subgs + nn; |
||||
|
||||
pp1 = loader->pp1; |
||||
pp2 = loader->pp2; |
||||
|
||||
num_base_points = gloader->base.outline.n_points; |
||||
|
||||
error = af_loader_load_g( loader, scaler, subglyph->index, |
||||
load_flags, depth + 1 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* recompute subglyph pointer */ |
||||
subglyph = gloader->base.subglyphs + num_base_subgs + nn; |
||||
|
||||
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) |
||||
{ |
||||
pp1 = loader->pp1; |
||||
pp2 = loader->pp2; |
||||
} |
||||
else |
||||
{ |
||||
loader->pp1 = pp1; |
||||
loader->pp2 = pp2; |
||||
} |
||||
|
||||
num_points = gloader->base.outline.n_points; |
||||
num_new_points = num_points - num_base_points; |
||||
|
||||
/* now perform the transform required for this subglyph */ |
||||
|
||||
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | |
||||
FT_SUBGLYPH_FLAG_XY_SCALE | |
||||
FT_SUBGLYPH_FLAG_2X2 ) ) |
||||
{ |
||||
FT_Vector* cur = gloader->base.outline.points + |
||||
num_base_points; |
||||
FT_Vector* org = gloader->base.extra_points + |
||||
num_base_points; |
||||
FT_Vector* limit = cur + num_new_points; |
||||
|
||||
|
||||
for ( ; cur < limit; cur++, org++ ) |
||||
{ |
||||
FT_Vector_Transform( cur, &subglyph->transform ); |
||||
FT_Vector_Transform( org, &subglyph->transform ); |
||||
} |
||||
} |
||||
|
||||
/* apply offset */ |
||||
|
||||
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) |
||||
{ |
||||
FT_Int k = subglyph->arg1; |
||||
FT_UInt l = subglyph->arg2; |
||||
FT_Vector* p1; |
||||
FT_Vector* p2; |
||||
|
||||
|
||||
if ( start_point + k >= num_base_points || |
||||
l >= (FT_UInt)num_new_points ) |
||||
{ |
||||
error = FT_Err_Invalid_Composite; |
||||
goto Exit; |
||||
} |
||||
|
||||
l += num_base_points; |
||||
|
||||
/* for now, only use the current point coordinates; */ |
||||
/* we may consider another approach in the near future */ |
||||
p1 = gloader->base.outline.points + start_point + k; |
||||
p2 = gloader->base.outline.points + start_point + l; |
||||
|
||||
x = p1->x - p2->x; |
||||
y = p1->y - p2->y; |
||||
} |
||||
else |
||||
{ |
||||
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta; |
||||
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta; |
||||
|
||||
x = FT_PIX_ROUND(x); |
||||
y = FT_PIX_ROUND(y); |
||||
} |
||||
|
||||
{ |
||||
FT_Outline dummy = gloader->base.outline; |
||||
|
||||
|
||||
dummy.points += num_base_points; |
||||
dummy.n_points = (short)num_new_points; |
||||
|
||||
FT_Outline_Translate( &dummy, x, y ); |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
/* we don't support other formats (yet?) */ |
||||
error = FT_Err_Unimplemented_Feature; |
||||
} |
||||
|
||||
Hint_Metrics: |
||||
if ( depth == 0 ) |
||||
{ |
||||
FT_BBox bbox; |
||||
|
||||
|
||||
/* transform the hinted outline if needed */ |
||||
if ( loader->transformed ) |
||||
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix ); |
||||
|
||||
/* we must translate our final outline by -pp1.x and compute */ |
||||
/* the new metrics */ |
||||
if ( loader->pp1.x ) |
||||
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 ); |
||||
|
||||
FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); |
||||
|
||||
bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); |
||||
bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); |
||||
bbox.xMax = FT_PIX_CEIL( bbox.xMax ); |
||||
bbox.yMax = FT_PIX_CEIL( bbox.yMax ); |
||||
|
||||
slot->metrics.width = bbox.xMax - bbox.xMin; |
||||
slot->metrics.height = bbox.yMax - bbox.yMin; |
||||
slot->metrics.horiBearingX = bbox.xMin; |
||||
slot->metrics.horiBearingY = bbox.yMax; |
||||
|
||||
/* for mono-width fonts (like Andale, Courier, etc.) we need */ |
||||
/* to keep the original rounded advance width */ |
||||
#if 0 |
||||
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) |
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
||||
else |
||||
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, |
||||
x_scale ); |
||||
#else |
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
||||
#endif |
||||
|
||||
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance ); |
||||
|
||||
/* now copy outline into glyph slot */ |
||||
FT_GlyphLoader_Rewind( loader->gloader ); |
||||
error = FT_GlyphLoader_CopyPoints( loader->gloader, gloader ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
slot->outline = slot->internal->loader->base.outline; |
||||
slot->format = FT_GLYPH_FORMAT_OUTLINE; |
||||
} |
||||
|
||||
#ifdef DEBUG_HINTER |
||||
af_debug_hinter = hinter; |
||||
#endif |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_load_glyph( AF_Loader loader, |
||||
FT_Face face, |
||||
FT_UInt gindex, |
||||
FT_UInt32 load_flags ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Size size = face->size; |
||||
AF_ScalerRec scaler; |
||||
|
||||
if ( !size ) |
||||
return FT_Err_Invalid_Argument; |
||||
|
||||
FT_ZERO( &scaler ); |
||||
|
||||
scaler.face = face; |
||||
scaler.x_scale = size->metrics.x_scale; |
||||
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ |
||||
scaler.y_scale = size->metrics.y_scale; |
||||
scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ |
||||
|
||||
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); |
||||
scaler.flags = 0; /* XXX: fix this */ |
||||
|
||||
error = af_loader_reset( loader, face ); |
||||
if ( !error ) |
||||
{ |
||||
AF_ScriptMetrics metrics; |
||||
|
||||
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics ); |
||||
if ( !error ) |
||||
{ |
||||
metrics->clazz->script_metrics_scale( metrics, &scaler ); |
||||
|
||||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; |
||||
load_flags &= ~FT_LOAD_RENDER; |
||||
|
||||
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 ); |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
#include "afloader.h" |
||||
#include "afhints.h" |
||||
#include "afglobal.h" |
||||
#include "aflatin.h" |
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_init( AF_Loader loader, |
||||
FT_Memory memory ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
FT_ZERO( loader ); |
||||
|
||||
af_glyph_hints_init( &loader->hints, memory ); |
||||
|
||||
error = FT_GlyphLoader_New( memory, &loader->gloader ); |
||||
if ( !error ) |
||||
{ |
||||
error = FT_GlyphLoader_CreateExtra( loader->gloader ); |
||||
if ( error ) |
||||
{ |
||||
FT_GlyphLoader_Done( loader->gloader ); |
||||
loader->gloader = NULL; |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_reset( AF_Loader loader, |
||||
FT_Face face ) |
||||
{ |
||||
FT_Error error = 0; |
||||
|
||||
loader->face = face; |
||||
loader->gloader = face->glyph->internal->loader; |
||||
loader->globals = (AF_FaceGlobals) face->autohint.data; |
||||
|
||||
if ( loader->globals == NULL ) |
||||
{ |
||||
error = af_face_globals_new( face, &loader->globals ); |
||||
if ( !error ) |
||||
{ |
||||
face->autohint.data = (FT_Pointer) loader->globals; |
||||
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free; |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF( void ) |
||||
af_loader_done( AF_Loader loader ) |
||||
{ |
||||
loader->face = NULL; |
||||
loader->globals = NULL; |
||||
|
||||
FT_GlyphLoader_Done( loader->gloader ); |
||||
loader->gloader = NULL; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
af_loader_load_g( AF_Loader loader, |
||||
AF_Scaler scaler, |
||||
FT_UInt glyph_index, |
||||
FT_Int32 load_flags, |
||||
FT_UInt depth ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Face face = loader->face; |
||||
AF_FaceGlobals globals = loader->globals; |
||||
FT_GlyphLoader gloader = loader->gloader; |
||||
AF_ScriptMetrics metrics = loader->metrics; |
||||
AF_GlyphHints hints = &loader->hints; |
||||
FT_GlyphSlot slot = face->glyph; |
||||
FT_Slot_Internal internal = slot->internal; |
||||
|
||||
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
loader->transformed = internal->glyph_transformed; |
||||
if ( loader->transformed ) |
||||
{ |
||||
FT_Matrix inverse; |
||||
|
||||
loader->trans_matrix = internal->glyph_matrix; |
||||
loader->trans_delta = internal->glyph_delta; |
||||
|
||||
inverse = loader->trans_matrix; |
||||
FT_Matrix_Invert( &inverse ); |
||||
FT_Vector_Transform( &loader->trans_delta, &inverse ); |
||||
} |
||||
|
||||
/* set linear metrics */ |
||||
slot->linearHoriAdvance = slot->metrics.horiAdvance; |
||||
slot->linearVertAdvance = slot->metrics.vertAdvance; |
||||
|
||||
switch ( slot->format ) |
||||
{ |
||||
case FT_GLYPH_FORMAT_OUTLINE: |
||||
/* translate the loaded glyph when an internal transform
|
||||
* is needed |
||||
*/ |
||||
if ( loader->transformed ) |
||||
{ |
||||
FT_Vector* point = slot->outline.points; |
||||
FT_Vector* limit = point + slot->outline.n_points; |
||||
|
||||
for ( ; point < limit; point++ ) |
||||
{ |
||||
point->x += loader->trans_delta.x; |
||||
point->y += loader->trans_delta.y; |
||||
} |
||||
} |
||||
|
||||
/* copy the outline points in the loader's current */ |
||||
/* extra points which is used to keep original glyph coordinates */ |
||||
error = FT_GlyphLoader_CheckPoints( gloader, |
||||
slot->outline.n_points + 2, |
||||
slot->outline.n_contours ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
FT_ARRAY_COPY( gloader->current.extra_points, |
||||
slot->outline.points, |
||||
slot->outline.n_points ); |
||||
|
||||
FT_ARRAY_COPY( gloader->current.outline.contours, |
||||
slot->outline.contours, |
||||
slot->outline.n_contours ); |
||||
|
||||
FT_ARRAY_COPY( gloader->current.outline.tags, |
||||
slot->outline.tags, |
||||
slot->outline.n_points ); |
||||
|
||||
gloader->current.outline.n_points = slot->outline.n_points; |
||||
gloader->current.outline.n_contours = slot->outline.n_contours; |
||||
|
||||
/* compute original phantom points */ |
||||
loader->pp1.x = hints->x_delta; |
||||
loader->pp1.y = hints->y_delta; |
||||
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, |
||||
hints->x_scale ) + hints->x_delta; |
||||
loader->pp2.y = hints->y_delta; |
||||
|
||||
/* be sure to check for spacing glyphs */ |
||||
if ( slot->outline.n_points == 0 ) |
||||
goto Hint_Metrics; |
||||
|
||||
/* now load the slot image into the auto-outline and run the */ |
||||
/* automatic hinting process */ |
||||
error = metrics->clazz->script_hints_init( hints, |
||||
&gloader->current.outline, |
||||
metrics ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* apply the hints */ |
||||
metrics->clazz->script_hints_apply( hints, |
||||
&gloader->current.outline, |
||||
metrics ); |
||||
/* we now need to hint the metrics according to the change in */ |
||||
/* width/positioning that occured during the hinting process */ |
||||
{ |
||||
FT_Pos old_advance, old_rsb, old_lsb, new_lsb; |
||||
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ]; |
||||
AF_Edge edge1 = axis->edges; /* leftmost edge */ |
||||
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */ |
||||
|
||||
|
||||
old_advance = loader->pp2.x; |
||||
old_rsb = old_advance - edge2->opos; |
||||
old_lsb = edge1->opos; |
||||
new_lsb = edge1->pos; |
||||
|
||||
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb ); |
||||
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb ); |
||||
|
||||
#if 0 |
||||
/* try to fix certain bad advance computations */ |
||||
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 ) |
||||
loader->pp2.x += 64; |
||||
#endif |
||||
} |
||||
|
||||
/* good, we simply add the glyph to our loader's base */ |
||||
FT_GlyphLoader_Add( gloader ); |
||||
break; |
||||
|
||||
case FT_GLYPH_FORMAT_COMPOSITE: |
||||
{ |
||||
FT_UInt nn, num_subglyphs = slot->num_subglyphs; |
||||
FT_UInt num_base_subgs, start_point; |
||||
FT_SubGlyph subglyph; |
||||
|
||||
|
||||
start_point = gloader->base.outline.n_points; |
||||
|
||||
/* first of all, copy the subglyph descriptors in the glyph loader */ |
||||
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
FT_ARRAY_COPY( gloader->current.subglyphs, |
||||
slot->subglyphs, |
||||
num_subglyphs ); |
||||
|
||||
gloader->current.num_subglyphs = num_subglyphs; |
||||
num_base_subgs = gloader->base.num_subglyphs; |
||||
|
||||
/* now, read each subglyph independently */ |
||||
for ( nn = 0; nn < num_subglyphs; nn++ ) |
||||
{ |
||||
FT_Vector pp1, pp2; |
||||
FT_Pos x, y; |
||||
FT_UInt num_points, num_new_points, num_base_points; |
||||
|
||||
|
||||
/* gloader.current.subglyphs can change during glyph loading due */ |
||||
/* to re-allocation -- we must recompute the current subglyph on */ |
||||
/* each iteration */ |
||||
subglyph = gloader->base.subglyphs + num_base_subgs + nn; |
||||
|
||||
pp1 = loader->pp1; |
||||
pp2 = loader->pp2; |
||||
|
||||
num_base_points = gloader->base.outline.n_points; |
||||
|
||||
error = af_loader_load_g( loader, scaler, subglyph->index, |
||||
load_flags, depth + 1 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* recompute subglyph pointer */ |
||||
subglyph = gloader->base.subglyphs + num_base_subgs + nn; |
||||
|
||||
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) |
||||
{ |
||||
pp1 = loader->pp1; |
||||
pp2 = loader->pp2; |
||||
} |
||||
else |
||||
{ |
||||
loader->pp1 = pp1; |
||||
loader->pp2 = pp2; |
||||
} |
||||
|
||||
num_points = gloader->base.outline.n_points; |
||||
num_new_points = num_points - num_base_points; |
||||
|
||||
/* now perform the transform required for this subglyph */ |
||||
|
||||
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | |
||||
FT_SUBGLYPH_FLAG_XY_SCALE | |
||||
FT_SUBGLYPH_FLAG_2X2 ) ) |
||||
{ |
||||
FT_Vector* cur = gloader->base.outline.points + |
||||
num_base_points; |
||||
FT_Vector* org = gloader->base.extra_points + |
||||
num_base_points; |
||||
FT_Vector* limit = cur + num_new_points; |
||||
|
||||
|
||||
for ( ; cur < limit; cur++, org++ ) |
||||
{ |
||||
FT_Vector_Transform( cur, &subglyph->transform ); |
||||
FT_Vector_Transform( org, &subglyph->transform ); |
||||
} |
||||
} |
||||
|
||||
/* apply offset */ |
||||
|
||||
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) |
||||
{ |
||||
FT_Int k = subglyph->arg1; |
||||
FT_UInt l = subglyph->arg2; |
||||
FT_Vector* p1; |
||||
FT_Vector* p2; |
||||
|
||||
|
||||
if ( start_point + k >= num_base_points || |
||||
l >= (FT_UInt)num_new_points ) |
||||
{ |
||||
error = FT_Err_Invalid_Composite; |
||||
goto Exit; |
||||
} |
||||
|
||||
l += num_base_points; |
||||
|
||||
/* for now, only use the current point coordinates; */ |
||||
/* we may consider another approach in the near future */ |
||||
p1 = gloader->base.outline.points + start_point + k; |
||||
p2 = gloader->base.outline.points + start_point + l; |
||||
|
||||
x = p1->x - p2->x; |
||||
y = p1->y - p2->y; |
||||
} |
||||
else |
||||
{ |
||||
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta; |
||||
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta; |
||||
|
||||
x = FT_PIX_ROUND(x); |
||||
y = FT_PIX_ROUND(y); |
||||
} |
||||
|
||||
{ |
||||
FT_Outline dummy = gloader->base.outline; |
||||
|
||||
|
||||
dummy.points += num_base_points; |
||||
dummy.n_points = (short)num_new_points; |
||||
|
||||
FT_Outline_Translate( &dummy, x, y ); |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
/* we don't support other formats (yet?) */ |
||||
error = FT_Err_Unimplemented_Feature; |
||||
} |
||||
|
||||
Hint_Metrics: |
||||
if ( depth == 0 ) |
||||
{ |
||||
FT_BBox bbox; |
||||
|
||||
|
||||
/* transform the hinted outline if needed */ |
||||
if ( loader->transformed ) |
||||
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix ); |
||||
|
||||
/* we must translate our final outline by -pp1.x and compute */ |
||||
/* the new metrics */ |
||||
if ( loader->pp1.x ) |
||||
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 ); |
||||
|
||||
FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); |
||||
|
||||
bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); |
||||
bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); |
||||
bbox.xMax = FT_PIX_CEIL( bbox.xMax ); |
||||
bbox.yMax = FT_PIX_CEIL( bbox.yMax ); |
||||
|
||||
slot->metrics.width = bbox.xMax - bbox.xMin; |
||||
slot->metrics.height = bbox.yMax - bbox.yMin; |
||||
slot->metrics.horiBearingX = bbox.xMin; |
||||
slot->metrics.horiBearingY = bbox.yMax; |
||||
|
||||
/* for mono-width fonts (like Andale, Courier, etc.) we need */ |
||||
/* to keep the original rounded advance width */ |
||||
#if 0 |
||||
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) |
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
||||
else |
||||
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, |
||||
x_scale ); |
||||
#else |
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
||||
#endif |
||||
|
||||
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance ); |
||||
|
||||
/* now copy outline into glyph slot */ |
||||
FT_GlyphLoader_Rewind( loader->gloader ); |
||||
error = FT_GlyphLoader_CopyPoints( loader->gloader, gloader ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
slot->outline = slot->internal->loader->base.outline; |
||||
slot->format = FT_GLYPH_FORMAT_OUTLINE; |
||||
} |
||||
|
||||
#ifdef DEBUG_HINTER |
||||
af_debug_hinter = hinter; |
||||
#endif |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error ) |
||||
af_loader_load_glyph( AF_Loader loader, |
||||
FT_Face face, |
||||
FT_UInt gindex, |
||||
FT_UInt32 load_flags ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Size size = face->size; |
||||
AF_ScalerRec scaler; |
||||
|
||||
if ( !size ) |
||||
return FT_Err_Invalid_Argument; |
||||
|
||||
FT_ZERO( &scaler ); |
||||
|
||||
scaler.face = face; |
||||
scaler.x_scale = size->metrics.x_scale; |
||||
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ |
||||
scaler.y_scale = size->metrics.y_scale; |
||||
scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ |
||||
|
||||
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags ); |
||||
scaler.flags = 0; /* XXX: fix this */ |
||||
|
||||
error = af_loader_reset( loader, face ); |
||||
if ( !error ) |
||||
{ |
||||
AF_ScriptMetrics metrics; |
||||
|
||||
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics ); |
||||
if ( !error ) |
||||
{ |
||||
metrics->clazz->script_metrics_scale( metrics, &scaler ); |
||||
|
||||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; |
||||
load_flags &= ~FT_LOAD_RENDER; |
||||
|
||||
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 ); |
||||
} |
||||
} |
||||
return error; |
||||
} |
||||
|
@ -1,50 +1,49 @@ |
||||
#ifndef __AF_LOADER_H__ |
||||
#define __AF_LOADER_H__ |
||||
|
||||
#include "afhints.h" |
||||
#include "afglobal.h" |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct AF_LoaderRec_ |
||||
{ |
||||
FT_Face face; /* current face */ |
||||
AF_FaceGlobals globals; /* current face globals */ |
||||
FT_GlyphLoader gloader; /* glyph loader */ |
||||
AF_GlyphHintsRec hints; |
||||
AF_ScriptMetrics metrics; |
||||
FT_Bool transformed; |
||||
FT_Matrix trans_matrix; |
||||
FT_Vector trans_delta; |
||||
FT_Vector pp1; |
||||
FT_Vector pp2; |
||||
|
||||
} AF_LoaderRec, *AF_Loader; |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_init( AF_Loader loader, |
||||
FT_Memory memory ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_reset( AF_Loader loader, |
||||
FT_Face face ); |
||||
|
||||
|
||||
FT_LOCAL( void ) |
||||
af_loader_done( AF_Loader loader ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_load_glyph( AF_Loader loader, |
||||
FT_Face face, |
||||
FT_UInt gindex, |
||||
FT_UInt32 load_flags ); |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __AF_LOADER_H__ */ |
||||
|
||||
#ifndef __AF_LOADER_H__ |
||||
#define __AF_LOADER_H__ |
||||
|
||||
#include "afhints.h" |
||||
#include "afglobal.h" |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
typedef struct AF_LoaderRec_ |
||||
{ |
||||
FT_Face face; /* current face */ |
||||
AF_FaceGlobals globals; /* current face globals */ |
||||
FT_GlyphLoader gloader; /* glyph loader */ |
||||
AF_GlyphHintsRec hints; |
||||
AF_ScriptMetrics metrics; |
||||
FT_Bool transformed; |
||||
FT_Matrix trans_matrix; |
||||
FT_Vector trans_delta; |
||||
FT_Vector pp1; |
||||
FT_Vector pp2; |
||||
|
||||
} AF_LoaderRec, *AF_Loader; |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_init( AF_Loader loader, |
||||
FT_Memory memory ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_reset( AF_Loader loader, |
||||
FT_Face face ); |
||||
|
||||
|
||||
FT_LOCAL( void ) |
||||
af_loader_done( AF_Loader loader ); |
||||
|
||||
|
||||
FT_LOCAL( FT_Error ) |
||||
af_loader_load_glyph( AF_Loader loader, |
||||
FT_Face face, |
||||
FT_UInt gindex, |
||||
FT_UInt32 load_flags ); |
||||
|
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __AF_LOADER_H__ */ |
||||
|
@ -1,17 +1,16 @@ |
||||
#ifndef __AFMODULE_H__ |
||||
#define __AFMODULE_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_MODULE_H |
||||
|
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
FT_CALLBACK_TABLE |
||||
const FT_Module_Class autofit_module_class; |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __AFMODULE_H__ */ |
||||
|
||||
#ifndef __AFMODULE_H__ |
||||
#define __AFMODULE_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_MODULE_H |
||||
|
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
FT_CALLBACK_TABLE |
||||
const FT_Module_Class autofit_module_class; |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __AFMODULE_H__ */ |
||||
|
@ -1,10 +1,8 @@ |
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT |
||||
#include <ft2build.h> |
||||
#include "afangles.c" |
||||
#include "afglobal.c" |
||||
#include "afhints.c" |
||||
#include "aflatin.c" |
||||
#include "afloader.c" |
||||
#include "afmodule.c" |
||||
|
||||
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT |
||||
#include <ft2build.h> |
||||
#include "afangles.c" |
||||
#include "afglobal.c" |
||||
#include "afhints.c" |
||||
#include "aflatin.c" |
||||
#include "afloader.c" |
||||
#include "afmodule.c" |
||||
|
Loading…
Reference in new issue