summaryrefslogtreecommitdiffstats
path: root/src/cache
diff options
context:
space:
mode:
authorJungshik Shin <jungshik@google.com>2016-01-15 16:18:25 -0800
committerThe Android Automerger <android-build@google.com>2016-02-24 13:20:13 -0800
commitf720f0dbcf012d6c984dbbefa0875ef9840458c6 (patch)
treebdb1068e64623c623100071dc586117aba4a2417 /src/cache
parentec62c527eb34ee4481a0153ceb42dfd35d7e1d26 (diff)
downloadandroid_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.tar.gz
android_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.tar.bz2
android_external_freetype-f720f0dbcf012d6c984dbbefa0875ef9840458c6.zip
[DO NOT MERGE] Update FreeType to 2.6.2 + update from 2.6.0
1. Update to a512b0fe7a (several patches past 2.6.2). Major changes include - stem-darkening is OFF for CFF fonts by default - general code tightening - header file location is back to include/freetype (used be include/) 2. A bit more details are added to README.android for the reference. This CL requires a pdfium change (the way it includes FT header files : https://googleplex-android-review.git.corp.google.com/#/c/846889 An AOSP master CL (https://android-review.googlesource.com/#/c/196504/) is ported to mnc-dev. Bug: 24296662 Change-Id: Iec6784838d89098f332e6d1ed79663efd91a8441 Signed-off-by: Jungshik Shin <jungshik@google.com>
Diffstat (limited to 'src/cache')
-rw-r--r--src/cache/ftcache.c31
-rw-r--r--src/cache/ftccache.c2
-rw-r--r--src/cache/ftcerror.h41
-rw-r--r--src/cache/ftcimage.c164
-rw-r--r--src/cache/ftcimage.h107
-rw-r--r--src/cache/ftcmanag.c703
-rw-r--r--src/cache/ftcmru.h246
7 files changed, 1293 insertions, 1 deletions
diff --git a/src/cache/ftcache.c b/src/cache/ftcache.c
new file mode 100644
index 0000000..8de527a
--- /dev/null
+++ b/src/cache/ftcache.c
@@ -0,0 +1,31 @@
+/***************************************************************************/
+/* */
+/* ftcache.c */
+/* */
+/* The FreeType Caching sub-system (body only). */
+/* */
+/* Copyright 2000-2015 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. */
+/* */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftcmru.c"
+#include "ftcmanag.c"
+#include "ftccache.c"
+#include "ftccmap.c"
+#include "ftcglyph.c"
+#include "ftcimage.c"
+#include "ftcsbits.c"
+#include "ftcbasic.c"
+
+/* END */
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index d8c5b99..b82a789 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -576,7 +576,7 @@
FTC_Node* pnode = bucket;
- for ( ;; )
+ for (;;)
{
FTC_Node node = *pnode;
FT_Bool list_changed = FALSE;
diff --git a/src/cache/ftcerror.h b/src/cache/ftcerror.h
new file mode 100644
index 0000000..15adec5
--- /dev/null
+++ b/src/cache/ftcerror.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* ftcerror.h */
+/* */
+/* Caching sub-system error codes (specification only). */
+/* */
+/* Copyright 2001-2015 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. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This file is used to define the caching sub-system error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FTCERROR_H__
+#define __FTCERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef FT_ERR_PREFIX
+#define FT_ERR_PREFIX FTC_Err_
+#define FT_ERR_BASE FT_Mod_Err_Cache
+
+#include FT_ERRORS_H
+
+#endif /* __FTCERROR_H__ */
+
+/* END */
diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c
new file mode 100644
index 0000000..f519a61
--- /dev/null
+++ b/src/cache/ftcimage.c
@@ -0,0 +1,164 @@
+/***************************************************************************/
+/* */
+/* ftcimage.c */
+/* */
+/* FreeType Image cache (body). */
+/* */
+/* Copyright 2000-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcimage.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /* finalize a given glyph image node */
+ FT_LOCAL_DEF( void )
+ ftc_inode_free( FTC_Node ftcinode,
+ FTC_Cache cache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Memory memory = cache->memory;
+
+
+ if ( inode->glyph )
+ {
+ FT_Done_Glyph( inode->glyph );
+ inode->glyph = NULL;
+ }
+
+ FTC_GNode_Done( FTC_GNODE( inode ), cache );
+ FT_FREE( inode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache )
+ {
+ ftc_inode_free( FTC_NODE( inode ), cache );
+ }
+
+
+ /* initialize a new glyph image node */
+ FT_LOCAL_DEF( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_INode inode = NULL;
+
+
+ if ( !FT_NEW( inode ) )
+ {
+ FTC_GNode gnode = FTC_GNODE( inode );
+ FTC_Family family = gquery->family;
+ FT_UInt gindex = gquery->gindex;
+ FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
+
+
+ /* initialize its inner fields */
+ FTC_GNode_Init( gnode, gindex, family );
+
+ /* we will now load the glyph image */
+ error = clazz->family_load_glyph( family, gindex, cache,
+ &inode->glyph );
+ if ( error )
+ {
+ FTC_INode_Free( inode, cache );
+ inode = NULL;
+ }
+ }
+
+ *pinode = inode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_inode_new( FTC_Node *ftcpinode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_INode *pinode = (FTC_INode*)ftcpinode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_INode_New( pinode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_Offset )
+ ftc_inode_weight( FTC_Node ftcinode,
+ FTC_Cache ftccache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Offset size = 0;
+ FT_Glyph glyph = inode->glyph;
+
+ FT_UNUSED( ftccache );
+
+
+ switch ( glyph->format )
+ {
+ case FT_GLYPH_FORMAT_BITMAP:
+ {
+ FT_BitmapGlyph bitg;
+
+
+ bitg = (FT_BitmapGlyph)glyph;
+ size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
+ sizeof ( *bitg );
+ }
+ break;
+
+ case FT_GLYPH_FORMAT_OUTLINE:
+ {
+ FT_OutlineGlyph outg;
+
+
+ outg = (FT_OutlineGlyph)glyph;
+ size = (FT_Offset)outg->outline.n_points *
+ ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
+ (FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +
+ sizeof ( *outg );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ size += sizeof ( *inode );
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_Offset )
+ FTC_INode_Weight( FTC_INode inode )
+ {
+ return ftc_inode_weight( FTC_NODE( inode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/cache/ftcimage.h b/src/cache/ftcimage.h
new file mode 100644
index 0000000..b312eaa
--- /dev/null
+++ b/src/cache/ftcimage.h
@@ -0,0 +1,107 @@
+/***************************************************************************/
+/* */
+/* ftcimage.h */
+/* */
+/* FreeType Generic Image cache (specification) */
+/* */
+/* Copyright 2000-2015 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_ICache is an _abstract_ cache used to store a single FT_Glyph
+ * image per cache node.
+ *
+ * FTC_ICache extends FTC_GCache. For an implementation example,
+ * see FTC_ImageCache in `src/cache/ftbasic.c'.
+ */
+
+
+ /*************************************************************************/
+ /* */
+ /* Each image cache really manages FT_Glyph objects. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCIMAGE_H__
+#define __FTCIMAGE_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+FT_BEGIN_HEADER
+
+
+ /* the FT_Glyph image node type - we store only 1 glyph per node */
+ typedef struct FTC_INodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_Glyph glyph;
+
+ } FTC_INodeRec, *FTC_INode;
+
+#define FTC_INODE( x ) ( (FTC_INode)( x ) )
+#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
+#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
+
+ typedef FT_Error
+ (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Cache cache,
+ FT_Glyph *aglyph );
+
+ typedef struct FTC_IFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_IFamily_LoadGlyphFunc family_load_glyph;
+
+ } FTC_IFamilyClassRec;
+
+ typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
+
+#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
+
+#define FTC_CACHE__IFAMILY_CLASS( x ) \
+ FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
+
+
+ /* can be used as a @FTC_Node_FreeFunc */
+ FT_LOCAL( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache );
+
+ /* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family'
+ * must be set correctly. This function will call the `family_load_glyph'
+ * method to load the FT_Glyph into the cache node.
+ */
+ FT_LOCAL( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+#if 0
+ /* can be used as @FTC_Node_WeightFunc */
+ FT_LOCAL( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode );
+#endif
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCIMAGE_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
new file mode 100644
index 0000000..658614c
--- /dev/null
+++ b/src/cache/ftcmanag.c
@@ -0,0 +1,703 @@
+/***************************************************************************/
+/* */
+/* ftcmanag.c */
+/* */
+/* FreeType Cache Manager (body). */
+/* */
+/* Copyright 2000-2015 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_SIZES_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "cache system does not support PIC yet"
+#endif
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cache
+
+
+ static FT_Error
+ ftc_scaler_lookup_size( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Face face;
+ FT_Size size = NULL;
+ FT_Error error;
+
+
+ error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
+ if ( error )
+ goto Exit;
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Exit;
+
+ FT_Activate_Size( size );
+
+ if ( scaler->pixel )
+ error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
+ else
+ error = FT_Set_Char_Size( face,
+ (FT_F26Dot6)scaler->width,
+ (FT_F26Dot6)scaler->height,
+ scaler->x_res,
+ scaler->y_res );
+ if ( error )
+ {
+ FT_Done_Size( size );
+ size = NULL;
+ }
+
+ Exit:
+ *asize = size;
+ return error;
+ }
+
+
+ typedef struct FTC_SizeNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FT_Size size;
+ FTC_ScalerRec scaler;
+
+ } FTC_SizeNodeRec, *FTC_SizeNode;
+
+#define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_size_node_done( FTC_MruNode ftcnode,
+ FT_Pointer data )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FT_Size size = node->size;
+ FT_UNUSED( data );
+
+
+ if ( size )
+ FT_Done_Size( size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_size_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Scaler scaler0 = &node->scaler;
+
+
+ if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
+ {
+ FT_Activate_Size( node->size );
+ return 1;
+ }
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_reset( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ FT_Done_Size( node->size );
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_size_list_class =
+ {
+ sizeof ( FTC_SizeNodeRec ),
+ ftc_size_node_compare,
+ ftc_size_node_init,
+ ftc_size_node_reset,
+ ftc_size_node_done
+ };
+
+
+ /* helper function used by ftc_face_node_done */
+ static FT_Bool
+ ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->scaler.face_id == face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !asize || !scaler )
+ return FT_THROW( Invalid_Argument );
+
+ *asize = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
+#endif
+
+ if ( !error )
+ *asize = FTC_SIZE_NODE( mrunode )->size;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FACE MRU IMPLEMENTATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct FTC_FaceNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FTC_FaceID face_id;
+ FT_Face face;
+
+ } FTC_FaceNodeRec, *FTC_FaceNode;
+
+#define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_face_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+ FT_Error error;
+
+
+ node->face_id = face_id;
+
+ error = manager->request_face( face_id,
+ manager->library,
+ manager->request_data,
+ &node->face );
+ if ( !error )
+ {
+ /* destroy initial size object; it will be re-created later */
+ if ( node->face->size )
+ FT_Done_Size( node->face->size );
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_face_node_done( FTC_MruNode ftcnode,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ /* we must begin by removing all scalers for the target face */
+ /* from the manager's list */
+ FTC_MruList_RemoveSelection( &manager->sizes,
+ ftc_size_node_compare_faceid,
+ node->face_id );
+
+ /* all right, we can discard the face now */
+ FT_Done_Face( node->face );
+ node->face = NULL;
+ node->face_id = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_face_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->face_id == face_id );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_face_list_class =
+ {
+ sizeof ( FTC_FaceNodeRec),
+
+ ftc_face_node_compare,
+ ftc_face_node_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ ftc_face_node_done
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !aface || !face_id )
+ return FT_THROW( Invalid_Argument );
+
+ *aface = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+ /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
+#endif
+
+ if ( !error )
+ *aface = FTC_FACE_NODE( mrunode )->face;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FTC_Manager manager = 0;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !amanager || !requester )
+ return FT_THROW( Invalid_Argument );
+
+ memory = library->memory;
+
+ if ( FT_NEW( manager ) )
+ goto Exit;
+
+ if ( max_faces == 0 )
+ max_faces = FTC_MAX_FACES_DEFAULT;
+
+ if ( max_sizes == 0 )
+ max_sizes = FTC_MAX_SIZES_DEFAULT;
+
+ if ( max_bytes == 0 )
+ max_bytes = FTC_MAX_BYTES_DEFAULT;
+
+ manager->library = library;
+ manager->memory = memory;
+ manager->max_weight = max_bytes;
+
+ manager->request_face = requester;
+ manager->request_data = req_data;
+
+ FTC_MruList_Init( &manager->faces,
+ &ftc_face_list_class,
+ max_faces,
+ manager,
+ memory );
+
+ FTC_MruList_Init( &manager->sizes,
+ &ftc_size_list_class,
+ max_sizes,
+ manager,
+ memory );
+
+ *amanager = manager;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Done( FTC_Manager manager )
+ {
+ FT_Memory memory;
+ FT_UInt idx;
+
+
+ if ( !manager || !manager->library )
+ return;
+
+ memory = manager->memory;
+
+ /* now discard all caches */
+ for (idx = manager->num_caches; idx-- > 0; )
+ {
+ FTC_Cache cache = manager->caches[idx];
+
+
+ if ( cache )
+ {
+ cache->clazz.cache_done( cache );
+ FT_FREE( cache );
+ manager->caches[idx] = NULL;
+ }
+ }
+ manager->num_caches = 0;
+
+ /* discard faces and sizes */
+ FTC_MruList_Done( &manager->sizes );
+ FTC_MruList_Done( &manager->faces );
+
+ manager->library = NULL;
+ manager->memory = NULL;
+
+ FT_FREE( manager );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Reset( FTC_Manager manager )
+ {
+ if ( !manager )
+ return;
+
+ FTC_MruList_Reset( &manager->sizes );
+ FTC_MruList_Reset( &manager->faces );
+
+ FTC_Manager_FlushN( manager, manager->num_nodes );
+ }
+
+
+#ifdef FT_DEBUG_ERROR
+
+ static void
+ FTC_Manager_Check( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ first = manager->nodes_list;
+
+ /* check node weights */
+ if ( first )
+ {
+ FT_Offset weight = 0;
+
+
+ node = first;
+
+ do
+ {
+ FTC_Cache cache = manager->caches[node->cache_index];
+
+
+ if ( (FT_UInt)node->cache_index >= manager->num_caches )
+ FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
+ node->cache_index ));
+ else
+ weight += cache->clazz.node_weight( node, cache );
+
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( weight != manager->cur_weight )
+ FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
+ manager->cur_weight, weight ));
+ }
+
+ /* check circular list */
+ if ( first )
+ {
+ FT_UFast count = 0;
+
+
+ node = first;
+ do
+ {
+ count++;
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( count != manager->num_nodes )
+ FT_TRACE0(( "FTC_Manager_Check:"
+ " invalid cache node count %d instead of %d\n",
+ manager->num_nodes, count ));
+ }
+ }
+
+#endif /* FT_DEBUG_ERROR */
+
+
+ /* `Compress' the manager's data, i.e., get rid of old cache nodes */
+ /* that are not referenced anymore in order to limit the total */
+ /* memory used by the cache. */
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( void )
+ FTC_Manager_Compress( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ if ( !manager )
+ return;
+
+ first = manager->nodes_list;
+
+#ifdef FT_DEBUG_ERROR
+ FTC_Manager_Check( manager );
+
+ FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
+ manager->cur_weight, manager->max_weight,
+ manager->num_nodes ));
+#endif
+
+ if ( manager->cur_weight < manager->max_weight || first == NULL )
+ return;
+
+ /* go to last node -- it's a circular list */
+ node = FTC_NODE__PREV( first );
+ do
+ {
+ FTC_Node prev;
+
+
+ prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
+
+ if ( node->ref_count <= 0 )
+ ftc_node_destroy( node, manager );
+
+ node = prev;
+
+ } while ( node && manager->cur_weight > manager->max_weight );
+ }
+
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Manager_RegisterCache( FTC_Manager manager,
+ FTC_CacheClass clazz,
+ FTC_Cache *acache )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FTC_Cache cache = NULL;
+
+
+ if ( manager && clazz && acache )
+ {
+ FT_Memory memory = manager->memory;
+
+
+ if ( manager->num_caches >= FTC_MAX_CACHES )
+ {
+ error = FT_THROW( Too_Many_Caches );
+ FT_ERROR(( "FTC_Manager_RegisterCache:"
+ " too many registered caches\n" ));
+ goto Exit;
+ }
+
+ if ( !FT_ALLOC( cache, clazz->cache_size ) )
+ {
+ cache->manager = manager;
+ cache->memory = memory;
+ cache->clazz = clazz[0];
+ cache->org_class = clazz;
+
+ /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
+ /* IF IT IS NOT SET CORRECTLY */
+ cache->index = manager->num_caches;
+
+ error = clazz->cache_init( cache );
+ if ( error )
+ {
+ clazz->cache_done( cache );
+ FT_FREE( cache );
+ goto Exit;
+ }
+
+ manager->caches[manager->num_caches++] = cache;
+ }
+ }
+
+ Exit:
+ if ( acache )
+ *acache = cache;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ FTC_Manager_FlushN( FTC_Manager manager,
+ FT_UInt count )
+ {
+ FTC_Node first = manager->nodes_list;
+ FTC_Node node;
+ FT_UInt result;
+
+
+ /* try to remove `count' nodes from the list */
+ if ( first == NULL ) /* empty list! */
+ return 0;
+
+ /* go to last node - it's a circular list */
+ node = FTC_NODE__PREV(first);
+ for ( result = 0; result < count; )
+ {
+ FTC_Node prev = FTC_NODE__PREV( node );
+
+
+ /* don't touch locked nodes */
+ if ( node->ref_count <= 0 )
+ {
+ ftc_node_destroy( node, manager );
+ result++;
+ }
+
+ if ( node == first )
+ break;
+
+ node = prev;
+ }
+ return result;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id )
+ {
+ FT_UInt nn;
+
+
+ if ( !manager || !face_id )
+ return;
+
+ /* this will remove all FTC_SizeNode that correspond to
+ * the face_id as well
+ */
+ FTC_MruList_RemoveSelection( &manager->faces,
+ ftc_face_node_compare,
+ face_id );
+
+ for ( nn = 0; nn < manager->num_caches; nn++ )
+ FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager )
+ {
+ if ( node &&
+ manager &&
+ (FT_UInt)node->cache_index < manager->num_caches )
+ node->ref_count--;
+ }
+
+
+/* END */
diff --git a/src/cache/ftcmru.h b/src/cache/ftcmru.h
new file mode 100644
index 0000000..c0c35f9
--- /dev/null
+++ b/src/cache/ftcmru.h
@@ -0,0 +1,246 @@
+/***************************************************************************/
+/* */
+/* ftcmru.h */
+/* */
+/* Simple MRU list-cache (specification). */
+/* */
+/* Copyright 2000-2015 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_LOCAL( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( 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_Bool
+ (*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_Offset 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_LOCAL( void )
+ FTC_MruList_Init( FTC_MruList list,
+ FTC_MruListClass clazz,
+ FT_UInt max_nodes,
+ FT_Pointer data,
+ FT_Memory memory );
+
+ FT_LOCAL( void )
+ FTC_MruList_Reset( FTC_MruList list );
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Done( FTC_MruList list );
+
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode );
+
+ FT_LOCAL( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node );
+
+ FT_LOCAL( 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 = FT_Err_Ok; \
+ _first = *(_pfirst); \
+ _node = NULL; \
+ \
+ if ( _first ) \
+ { \
+ _node = _first; \
+ do \
+ { \
+ if ( _compare( _node, (key) ) ) \
+ { \
+ if ( _node != _first ) \
+ FTC_MruNode_Up( _pfirst, _node ); \
+ \
+ node = _node; \
+ goto _MruOk; \
+ } \
+ _node = _node->next; \
+ \
+ } while ( _node != _first) ; \
+ } \
+ \
+ error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(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 */
+
+ FT_LOCAL( FTC_MruNode )
+ FTC_MruList_Find( FTC_MruList list,
+ FT_Pointer key );
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *pnode );
+
+#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 */