Commit 843997b2 authored by David Turner's avatar David Turner
Browse files

small updates:

 - reworked slightly the cache manager to better
   differentiate between the abstract class in "ftcglyph.h"
   and the FT_Glyph sub-class in "ftcimage.h", and
   slightly reduced the size of FTC_GlyphNodeRec, saving
   8 bytes on a 32-bit system. Yes, I'm crazy ;-)

 - added build files to compile with LCC on Unix too
   (compile speeds _are_ insane with it). There is unfortunately
   a bug in the version I'm using (LCC 4.1) that prevents it
   to compile FT_MulTo64 correctly (in src/base/ftcalc.c)

   the generated assembly is incorrect, I don't know what
   to do ?? the build files are ok, though..

   you should invoke "make setup lcc" to select them..
parent 7974b6ec
#
# FreeType 2 Unix LCC specific definitions
#
# Copyright 1996-2000 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
# and distributed under the terms of the FreeType project license,
# LICENSE.TXT. By continuing to use, modify, or distribute this file you
# indicate that you have read the license and understand and accept it
# fully.
# Command line name
#
CC := lcc
# The object file extension (for standard and static libraries). This can be
# .o, .tco, .obj, etc., depending on the platform.
#
O := o
SO := o
# The library file extension (for standard and static libraries). This can
# be .a, .lib, etc., depending on the platform.
#
A := a
SA := a
# Path inclusion flag. Some compilers use a different flag than `-I' to
# specify an additional include path. Examples are `/i=' or `-J'.
#
I := -I
# C flag used to define a macro before the compilation of a given source
# object. Usually it is `-D' like in `-DDEBUG'.
#
D := -D
# The link flag used to specify a given library file on link. Note that
# this is only used to compile the demo programs, not the library itself.
#
L := -l
# Target flag.
#
T := -o # don't remove this comment, we need a trailing space !!
# C flags
#
# These should concern: debug output, optimization & warnings.
#
# Use the ANSIFLAGS variable to define the compiler flags used to enfore
# ANSI compliance.
#
ifndef CFLAGS
CFLAGS := -c -g
endif
# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
#
# LCC is pure ANSI anyway!
#
# the "-A" flag simply increments verbosity about non ANSI code
#
ANSIFLAGS := -A
# library linking
#
ifndef CLEAN_LIBRARY
CLEAN_LIBRARY = $(DELETE) $(subst $(SEP),$(HOSTSEP),$(PROJECT_LIBRARY)) \
$(NO_OUTPUT)
endif
LINK_LIBRARY = $(AR) -r $@ $(OBJECTS_LIST)
# EOF
......@@ -30,21 +30,30 @@ ifeq ($(PLATFORM),ansi)
CONFIG_FILE := unix-dev.mk
devel: setup
else
# If a Unix platform is detected, the configure script is called and
# `unix-def.mk' together with `unix-cc.mk' is created.
#
# Arguments to `configure' should be in the CFG variable. Example:
#
# make CFG="--prefix=/usr --disable-static"
#
# If you need to set CFLAGS or LDFLAGS, do it here also.
#
# Feel free to add support for other platform specific compilers in this
# directory (e.g. solaris.mk + changes here to detect the platform).
#
CONFIG_FILE := unix.mk
setup: unix-def.mk
unix: setup
# If `lccl' is the requested target, we use a special configuration
# file named `unix-lcc.mk'. It disables libtool for LCC
#
ifneq ($(findstring lcc,$(MAKECMDGOALS)),)
CONFIG_FILE := unix-lcc.mk
lcc: setup
else
# If a Unix platform is detected, the configure script is called and
# `unix-def.mk' together with `unix-cc.mk' is created.
#
# Arguments to `configure' should be in the CFG variable. Example:
#
# make CFG="--prefix=/usr --disable-static"
#
# If you need to set CFLAGS or LDFLAGS, do it here also.
#
# Feel free to add support for other platform specific compilers in this
# directory (e.g. solaris.mk + changes here to detect the platform).
#
CONFIG_FILE := unix.mk
setup: unix-def.mk
unix: setup
endif
endif
setup: std_setup
......
#
# FreeType 2 Configuration rules for Unix + LCC
#
# Development version without optimizations & libtool
# and no installation.
#
# Copyright 1996-2000 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
# and distributed under the terms of the FreeType project license,
# LICENSE.TXT. By continuing to use, modify, or distribute this file you
# indicate that you have read the license and understand and accept it
# fully.
include $(TOP)/builds/unix/unixddef.mk
include $(TOP)/builds/compiler/unix-lcc.mk
include $(TOP)/builds/link_std.mk
# EOF
......@@ -49,7 +49,6 @@
#include <freetype/cache/ftcmanag.h>
#include <freetype/ftglyph.h>
#include <stddef.h>
......@@ -58,7 +57,7 @@
#endif
/* maximum number of queues per image cache; must be < 256 */
/* maximum number of queues per glyph cache; must be < 256 */
#define FTC_MAX_GLYPH_QUEUES 16
#define FTC_QUEUE_HASH_SIZE_DEFAULT 64
......@@ -70,35 +69,14 @@
typedef struct FTC_GlyphNodeRec_
{
FTC_CacheNodeRec root;
/* link.data contains a handle to a FT_Glyph object */
FT_ListNodeRec link;
FTC_GlyphNode queue_next; /* next in queue's bucket list */
FT_UShort glyph_index;
FT_UShort queue_index;
} FTC_GlyphNodeRec;
#define FTC_GLYPHNODE_GET_GLYPH( n ) \
( (FT_Glyph)((n)->link.data) )
#define FTC_GLYPHNODE_SET_GLYPH( n, g ) \
do \
{ \
(n)->link.data = (g); \
} while ( 0 )
/* this macro is used to extract a handle to the bucket's lru list */
/* corresponding to a given image node */
#define FTC_GLYPHNODE_TO_LISTNODE( n ) \
( (FT_ListNode)&(n)->link )
/* this macro is used to extract a handle to a given image node from */
/* the corresponding LRU glyph list node. That's a bit hackish... */
#define FTC_LISTNODE_TO_GLYPHNODE( p ) \
( (FTC_GlyphNode)( (char*)(p) - \
offsetof( FTC_GlyphNodeRec,link ) ) )
#define FTC_GLYPHNODE(x) ( (FTC_GlyphNode)(x) )
#define FTC_GLYPHNODE_TO_LRUNODE( n ) ( (FT_ListNode)(n) )
#define FTC_LRUNODE_TO_GLYPHNODE( n ) ( (FTC_GlyphNode)(n) )
......@@ -150,7 +128,7 @@
FTC_Glyph_Queue_Class* clazz;
FTC_Image_Desc descriptor;
FT_UInt hash_size;
FT_List buckets;
FTC_GlyphNode* buckets;
FT_UInt queue_index; /* index in parent cache */
} FTC_Glyph_QueueRec;
......@@ -170,7 +148,7 @@
{
FTC_CacheRec root;
FT_Lru queues_lru; /* static queues lru list */
FTC_Glyph_Queue last_queue; /* small cache */
FTC_Glyph_Queue last_queue; /* small cache :-) */
} FTC_Glyph_CacheRec;
......@@ -182,9 +160,10 @@
/* cache sub-system internals. */
/* */
FT_EXPORT_FUNC( void ) FTC_GlyphNode_Init( FTC_GlyphNode node,
FTC_Glyph_Queue queue,
FT_UInt gindex );
FT_EXPORT_FUNC( void )
FTC_GlyphNode_Init( FTC_GlyphNode node,
FTC_Glyph_Queue queue,
FT_UInt gindex );
#define FTC_GlyphNode_Ref( n ) \
FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++
......@@ -193,21 +172,30 @@
FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count--
FT_EXPORT_DEF( void ) FTC_Destroy_Glyph_Node( FTC_GlyphNode node,
FTC_Glyph_Cache cache );
FT_EXPORT_DEF( void )
FTC_Destroy_Glyph_Node( FTC_GlyphNode node,
FTC_Glyph_Cache cache );
FT_EXPORT_DEF( FT_Error )
FTC_Glyph_Cache_Init( FTC_Glyph_Cache cache );
FT_EXPORT_DEF( void )
FTC_Glyph_Cache_Done( FTC_Glyph_Cache cache );
FT_EXPORT_DEF( FT_Error ) FTC_Glyph_Cache_Init( FTC_Glyph_Cache cache );
FT_EXPORT_DEF( void ) FTC_Glyph_Cache_Done( FTC_Glyph_Cache cache );
FT_EXPORT_DEF( FT_Error )
FTC_Glyph_Queue_New( FTC_Glyph_Cache cache,
FT_Pointer type,
FTC_Glyph_Queue* aqueue );
FT_EXPORT_DEF( FT_Error ) FTC_Glyph_Queue_New( FTC_Glyph_Cache cache,
FT_Pointer type,
FTC_Glyph_Queue* aqueue );
FT_EXPORT_DEF( FT_Error ) FTC_Glyph_Queue_Lookup_Node(
FTC_Glyph_Queue queue,
FT_EXPORT_DEF( FT_Error )
FTC_Glyph_Queue_Lookup_Node( FTC_Glyph_Queue queue,
FT_UInt glyph_index,
FTC_GlyphNode* anode );
......
......@@ -74,9 +74,9 @@
/* default values */
#define FTC_MAX_FACES_DEFAULT 4
#define FTC_MAX_SIZES_DEFAULT 8
#define FTC_MAX_BYTES_DEFAULT 300000 /* 300kByte by default! */
#define FTC_MAX_FACES_DEFAULT 2
#define FTC_MAX_SIZES_DEFAULT 4
#define FTC_MAX_BYTES_DEFAULT 200000 /* 200kByte by default! */
/* maximum number of caches registered in a single manager */
#define FTC_MAX_CACHES 16
......@@ -114,7 +114,7 @@
/* 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 hold by */
/* 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. */
/* */
......@@ -123,7 +123,7 @@
typedef FTC_CacheNodeRec* FTC_CacheNode;
/* the fields `cachenode.data' is typecast to this type */
/* the fields `cachenode.data' is typecasted to this type */
typedef struct FTC_CacheNode_Data_
{
FT_UShort cache_index;
......@@ -169,8 +169,7 @@
typedef FT_Error (*FTC_Cache_InitFunc)( FTC_Cache cache );
typedef void (*FTC_Cache_DoneFunc)( FTC_Cache cache );
typedef void (*FTC_Cache_DoneFunc)( FTC_Cache cache );
struct FTC_Cache_Class_
......
......@@ -20,7 +20,7 @@
/* */
/* An LRU is a list that cannot hold more than a certain number of */
/* elements (`max_elements'). All elements on the list are sorted in */
/* lest-recently-used order, i.e., the `oldest' element is at the tail */
/* 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()'), */
......
......@@ -65,7 +65,7 @@
/* Important: This function is called from the cache manager to */
/* destroy a given cache node during `cache compression'. The */
/* second argument is always `cache.user_data'. Thus be */
/* certain that the function FTC_Image_Cache_New() does indeed */
/* certain that the function FTC_Glyph_Cache_New() does indeed */
/* set its `user_data' field correctly, otherwise bad things */
/* will happen! */
......@@ -75,11 +75,31 @@
FT_LruNode queue_lru = cache->queues_lru->nodes + node->queue_index;
FTC_Glyph_Queue queue = (FTC_Glyph_Queue)queue_lru->root.data;
FT_UInt hash = node->glyph_index % queue->hash_size;
FT_List bucket = queue->buckets + hash;
/* remove node from its queue's bucket list */
FT_List_Remove( bucket, FTC_GLYPHNODE_TO_LISTNODE( node ) );
/* remove the node from its queue's bucket list */
{
FTC_GlyphNode* pnode = queue->buckets + hash;
FTC_GlyphNode cur;
for (;;)
{
cur = *pnode;
if (!cur)
{
/* that's very strange, this should not happen !! */
FT_ERROR(( "FTC_GlyphNode_Destroy:"
" trying to delete an unlisted node !!!!" ));
return;
}
if (cur == node)
{
*pnode = cur->queue_next;
break;
}
pnode = &cur->queue_next;
}
}
/* destroy the node */
queue->clazz->destroy_node( node, queue );
......@@ -89,7 +109,7 @@
/* Important: This function is called from the cache manager to */
/* size a given cache node during `cache compression'. The */
/* second argument is always `cache.user_data'. Thus be */
/* certain that the function FTC_Image_Cache_New() does indeed */
/* certain that the function FTC_Glyph_Cache_New() does indeed */
/* set its `user_data' field correctly, otherwise bad things */
/* will happen! */
......@@ -148,7 +168,7 @@
queue->clazz = clazz;
/* allocate buckets table */
if ( ALLOC_ARRAY( queue->buckets, queue->hash_size, FT_ListRec ) )
if ( ALLOC_ARRAY( queue->buckets, queue->hash_size, FTC_GlyphNode ) )
goto Exit;
/* initialize queue by type if needed */
......@@ -177,8 +197,8 @@
FTC_Glyph_Cache cache = queue->cache;
FTC_Manager manager = cache->root.manager;
FT_List glyphs_lru = &manager->global_lru;
FT_List bucket = queue->buckets;
FT_List bucket_limit = bucket + queue->hash_size;
FTC_GlyphNode* bucket = queue->buckets;
FTC_GlyphNode* bucket_limit = bucket + queue->hash_size;
FT_Memory memory = cache->root.memory;
FTC_Glyph_Queue_Class* clazz = queue->clazz;
......@@ -187,26 +207,24 @@
/* for each bucket, free the list of glyph nodes */
for ( ; bucket < bucket_limit; bucket++ )
{
FT_ListNode node = bucket->head;
FT_ListNode next = 0;
FT_ListNode lrunode;
FTC_GlyphNode inode;
FTC_GlyphNode node = bucket[0];
FTC_GlyphNode next = 0;
FT_ListNode lrunode;
for ( ; node; node = next )
{
next = node->next;
inode = FTC_LISTNODE_TO_GLYPHNODE( node );
lrunode = FTC_GLYPHNODE_TO_LRUNODE( inode );
next = node->queue_next;
lrunode = FTC_GLYPHNODE_TO_LRUNODE( node );
manager->num_bytes -= clazz->size_node( inode, queue );
manager->num_bytes -= clazz->size_node( node, queue );
FT_List_Remove( glyphs_lru, lrunode );
clazz->destroy_node( inode, queue );
clazz->destroy_node( node, queue );
}
bucket->head = bucket->tail = 0;
bucket[0] = 0;
}
if ( clazz->done )
......@@ -217,58 +235,63 @@
}
FT_EXPORT_FUNC( FT_Error ) FTC_Glyph_Queue_Lookup_Node(
FTC_Glyph_Queue queue,
FT_UInt glyph_index,
FTC_GlyphNode* anode )
FT_EXPORT_FUNC( FT_Error )
FTC_Glyph_Queue_Lookup_Node( FTC_Glyph_Queue queue,
FT_UInt glyph_index,
FTC_GlyphNode* anode )
{
FTC_Glyph_Cache cache = queue->cache;
FTC_Manager manager = cache->root.manager;
FT_UInt hash_index = glyph_index % queue->hash_size;
FT_List bucket = queue->buckets + hash_index;
FT_ListNode node;
FTC_GlyphNode* bucket = queue->buckets + hash_index;
FTC_GlyphNode* pnode = bucket;
FTC_GlyphNode node;
FT_Error error;
FTC_GlyphNode inode;
FTC_Glyph_Queue_Class* clazz = queue->clazz;
*anode = 0;
for ( node = bucket->head; node; node = node->next )
for ( ;; )
{
FT_UInt gindex;
inode = FTC_LISTNODE_TO_GLYPHNODE( node );
gindex = inode->glyph_index;
if ( gindex == glyph_index )
node = *pnode;
if (!node)
break;
if ( node->glyph_index == glyph_index )
{
/* we found it! -- move glyph to start of the lists */
FT_List_Up( bucket, node );
FT_List_Up( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( inode ) );
*anode = inode;
*pnode = node->queue_next;
node->queue_next = bucket[0];
bucket[0] = node;
FT_List_Up( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
*anode = node;
return 0;
}
/* go to next node in bucket */
pnode = &node->queue_next;
}
/* we didn't found the glyph image, we will now create a new one */
error = clazz->new_node( queue, glyph_index, &inode );
error = clazz->new_node( queue, glyph_index, &node );
if ( error )
goto Exit;
/* insert the node at the start of our bucket list */
FT_List_Insert( bucket, FTC_GLYPHNODE_TO_LISTNODE( inode ) );
node->queue_next = bucket[0];
bucket[0] = node;
/* insert the node at the start the global LRU glyph list */
FT_List_Insert( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( inode ) );
FT_List_Insert( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
manager->num_bytes += clazz->size_node( inode, queue );
manager->num_bytes += clazz->size_node( node, queue );
if (manager->num_bytes > manager->max_bytes)
FTC_Manager_Compress( manager );
*anode = inode;
*anode = node;
Exit:
return error;
......
......@@ -39,13 +39,13 @@
/* this is a simple glyph image destructor, which is called exclusively */
/* from the CacheQueue object */
LOCAL_FUNC_X
void ftc_glyph_image_node_destroy( FTC_GlyphNode node,
void ftc_glyph_image_node_destroy( FTC_GlyphImage node,
FTC_Glyph_Queue queue )
{
FT_Memory memory = queue->memory;
FT_Done_Glyph( FTC_GLYPHNODE_GET_GLYPH( node ) );
FT_Done_Glyph( node->ft_glyph );
FREE( node );
}
......@@ -53,12 +53,12 @@
LOCAL_FUNC_X
FT_Error ftc_glyph_image_node_new( FTC_Glyph_Queue queue,
FT_UInt glyph_index,
FTC_GlyphNode* anode )
FTC_GlyphImage *anode )
{
FT_Memory memory = queue->memory;
FTC_Image_Queue imageq = (FTC_Image_Queue)queue;
FT_Error error;
FTC_GlyphNode node = 0;
FTC_GlyphImage node = 0;
FT_Face face;
FT_Size size;
......@@ -68,7 +68,7 @@
goto Exit;
/* init its inner fields */
FTC_GlyphNode_Init( node, queue, glyph_index );
FTC_GlyphNode_Init( FTC_GLYPHNODE(node), queue, glyph_index );
/* we will now load the glyph image */
error = FTC_Manager_Lookup_Size( queue->manager,
......@@ -76,7 +76,7 @@
&face, &size );
if ( !error )
{
FT_UInt glyph_index = node->glyph_index;
FT_UInt glyph_index = node->root.glyph_index;
FT_UInt load_flags = FT_LOAD_DEFAULT;
FT_UInt image_type = imageq->description.image_type;
......@@ -118,7 +118,7 @@
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
FTC_GLYPHNODE_SET_GLYPH( node, glyph );
node->ft_glyph = glyph;
}
else
error = FT_Err_Invalid_Argument;
......@@ -138,10 +138,10 @@
/* a FTC_Glyph_Queue_Class and a FTC_CacheNode_Class */
/* */
LOCAL_FUNC_X
FT_ULong ftc_glyph_image_node_size( FTC_GlyphNode node )
FT_ULong ftc_glyph_image_node_size( FTC_GlyphImage node )
{
FT_ULong size = 0;
FT_Glyph glyph = FTC_GLYPHNODE_GET_GLYPH( node );
FT_Glyph glyph = node->ft_glyph;
switch ( glyph->format )
......@@ -249,15 +249,15 @@
}
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_Lookup(
FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph* aglyph )
FT_EXPORT_DEF( FT_Error )
FTC_Image_Cache_Lookup( FTC_Image_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph* aglyph )
{
FT_Error error;
FTC_Glyph_Queue queue;
FTC_GlyphNode inode;
FTC_GlyphNode node;
FTC_Manager manager;
FTC_Image_Queue img_queue;
......@@ -281,7 +281,7 @@
goto Exit;
}
error = FTC_Glyph_Queue_Lookup_Node( queue, gindex, &inode );
error = FTC_Glyph_Queue_Lookup_Node( queue, gindex, &node );
if ( error )
goto Exit;
......@@ -289,12 +289,12 @@
manager = cache->root.root.manager;
if ( manager->num_bytes > manager->max_bytes )
{
FTC_GlyphNode_Ref( inode );
FTC_GlyphNode_Ref ( node );
FTC_Manager_Compress( manager );
FTC_GlyphNode_Unref( inode );
FTC_GlyphNode_Unref ( node );