ref: 80b96f350c8ea73f7da0dd76fc5c075dcbfdfaa9
parent: e12e313a04c8340c1b8adae0c59dd1e76f56e2eb
author: David Turner <[email protected]>
date: Tue Aug 29 12:04:28 EDT 2000
fixed some bugs in the caching sub-system and improved its API to enable many kinds of glyph images.. (note that the "ftview" program has been changed to use the caching sub-system, "ftmulti" and "ftstring" should come soon).
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -318,12 +318,26 @@
/* <Note> */
/* Other types may be defined in the future. */
/* */
+
+#define FTC_IMAGE_FORMAT(x) ((x) & 7)
+
typedef enum FTC_Image_Type_
{
- ftc_image_mono = 0, /* monochrome bitmap */
- ftc_image_grays, /* anti-aliased bitmap */
- ftc_image_outline, /* scaled outline */
- ftc_image_master_outline /* original outline */
+ ftc_image_format_bitmap = 0,
+ ftc_image_format_outline = 1,
+
+ ftc_image_flag_monochrome = 16,
+ ftc_image_flag_unhinted = 32,
+ ftc_image_flag_autohinted = 64,
+ ftc_image_flag_unscaled = 128,
+ ftc_image_flag_no_sbits = 256,
+
+ ftc_image_mono = ftc_image_format_bitmap |
+ ftc_image_flag_monochrome, /* monochrome bitmap */
+
+ ftc_image_grays = ftc_image_format_bitmap, /* anti-aliased bitmap */
+
+ ftc_image_outline = ftc_image_format_outline /* scaled outline */
} FTC_Image_Type;
--- a/src/cache/ftcimage.c
+++ b/src/cache/ftcimage.c
@@ -20,6 +20,7 @@
#include <freetype/fterrors.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftlist.h>
+#include <freetype/fterrors.h>
/**************************************************************************/
/**************************************************************************/
@@ -123,8 +124,8 @@
static
- FT_Error ftc_init_mono_image( FTC_Image_Queue queue,
- FTC_ImageNode node )
+ FT_Error ftc_init_glyph_image( FTC_Image_Queue queue,
+ FTC_ImageNode node )
{
FT_Face face;
FT_Size size;
@@ -136,105 +137,40 @@
if ( !error )
{
FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
-
+ FT_UInt load_flags = FT_LOAD_DEFAULT;
+ FT_UInt image_type = queue->descriptor.image_type;
- error = FT_Load_Glyph( face, glyph_index,
- FT_LOAD_RENDER | FT_LOAD_MONOCHROME );
- if ( !error )
- {
- if ( face->glyph->format != ft_glyph_format_bitmap ||
- face->glyph->bitmap.pixel_mode != ft_pixel_mode_mono )
- {
- /* there is no monochrome glyph for this font! */
- error = FT_Err_Invalid_Glyph_Index;
- }
- else
- {
- /* ok, copy it */
- FT_Glyph glyph;
+ if ( FTC_IMAGE_FORMAT(image_type) == ftc_image_format_bitmap )
+ {
+ load_flags |= FT_LOAD_RENDER;
+ if ( image_type & ftc_image_flag_monochrome )
+ load_flags |= FT_LOAD_MONOCHROME;
-
- error = FT_Get_Glyph( face->glyph, &glyph );
- if ( !error )
- FTC_IMAGENODE_SET_GLYPH( node, glyph );
- }
+ /* disable embedded bitmaps loading if necessary */
+ if (load_flags & ftc_image_flag_no_sbits)
+ load_flags |= FT_LOAD_NO_BITMAP;
}
- }
- return error;
- }
-
-
- static
- FT_Error ftc_init_gray_image( FTC_Image_Queue queue,
- FTC_ImageNode node )
- {
- FT_Face face;
- FT_Size size;
- FT_Error error;
-
-
- error = FTC_Manager_Lookup_Size( queue->manager,
- &queue->descriptor.size,
- &face, &size );
- if ( !error )
- {
- FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
-
-
- error = FT_Load_Glyph( face, glyph_index,
- FT_LOAD_RENDER );
- if ( !error )
+ else if ( FTC_IMAGE_FORMAT(image_type) == ftc_image_format_outline )
{
- if ( face->glyph->format != ft_glyph_format_bitmap ||
- face->glyph->bitmap.pixel_mode != ft_pixel_mode_grays )
- {
- /* there is no anti-aliased glyph for this font! */
- error = FT_Err_Invalid_Glyph_Index;
- }
- else
- {
- /* ok, copy it */
- FT_Glyph glyph;
+ /* disable embedded bitmaps loading */
+ load_flags |= FT_LOAD_NO_BITMAP;
+
+ if (image_type & ftc_image_flag_unscaled)
+ load_flags |= FT_LOAD_NO_SCALE;
+ }
+ if (image_type & ftc_image_flag_unhinted)
+ load_flags |= FT_LOAD_NO_HINTING;
- error = FT_Get_Glyph( face->glyph, &glyph );
- if ( !error )
- FTC_IMAGENODE_SET_GLYPH( node, glyph );
- }
- }
- }
- return error;
- }
+ if (image_type & ftc_image_flag_autohinted)
+ load_flags |= FT_LOAD_FORCE_AUTOHINT;
-
- static
- FT_Error ftc_init_outline_image( FTC_Image_Queue queue,
- FTC_ImageNode node )
- {
- FT_Face face;
- FT_Size size;
- FT_Error error;
-
-
- error = FTC_Manager_Lookup_Size( queue->manager,
- &queue->descriptor.size,
- &face, &size );
- if ( !error )
- {
- FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
-
-
- error = FT_Load_Glyph( face, glyph_index,
- FT_LOAD_NO_BITMAP );
+ error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( !error )
{
- if ( face->glyph->format != ft_glyph_format_outline )
- {
- /* there is no outline glyph for this font! */
- error = FT_Err_Invalid_Glyph_Index;
- }
- else
- {
+ if ( face->glyph->format == ft_glyph_format_bitmap ||
+ face->glyph->format == ft_glyph_format_outline )
+ {
/* ok, copy it */
FT_Glyph glyph;
@@ -243,6 +179,8 @@
if ( !error )
FTC_IMAGENODE_SET_GLYPH( node, glyph );
}
+ else
+ error = FT_Err_Invalid_Argument;
}
}
return error;
@@ -250,81 +188,25 @@
- static
- FT_Error ftc_init_master_outline_image( FTC_Image_Queue queue,
- FTC_ImageNode node )
- {
- FT_Face face;
- FT_Size size;
- FT_Error error;
-
- error = FTC_Manager_Lookup_Size( queue->manager,
- &queue->descriptor.size,
- &face, &size );
- if ( !error )
- {
- FT_UInt glyph_index = FTC_IMAGENODE_GET_GINDEX( node );
-
- error = FT_Load_Glyph( face, glyph_index,
- FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
- if ( !error )
- {
- if ( face->glyph->format != ft_glyph_format_outline )
- {
- /* there is no outline glyph for this font! */
- error = FT_Err_Invalid_Glyph_Index;
- }
- else
- {
- /* ok, copy it */
- FT_Glyph glyph;
-
-
- error = FT_Get_Glyph( face->glyph, &glyph );
- if ( !error )
- FTC_IMAGENODE_SET_GLYPH( node, glyph );
- }
- }
- }
- return error;
- }
-
-
static
- const FTC_Image_Class ftc_mono_image_class =
+ const FTC_Image_Class ftc_bitmap_image_class =
{
- ftc_init_mono_image,
+ ftc_init_glyph_image,
ftc_done_glyph_image,
ftc_size_bitmap_image
};
static
- const FTC_Image_Class ftc_gray_image_class =
- {
- ftc_init_gray_image,
- ftc_done_glyph_image,
- ftc_size_bitmap_image
- };
-
- static
const FTC_Image_Class ftc_outline_image_class =
{
- ftc_init_outline_image,
+ ftc_init_glyph_image,
ftc_done_glyph_image,
ftc_size_outline_image
};
- static
- const FTC_Image_Class ftc_master_outline_image_class =
- {
- ftc_init_master_outline_image,
- ftc_done_glyph_image,
- ftc_size_outline_image
- };
-
static
FT_Error FTC_Image_Queue_New( FTC_Image_Cache cache,
FTC_Image_Desc* desc,
@@ -346,33 +228,25 @@
queue->manager = manager;
queue->memory = memory;
queue->descriptor = *desc;
- queue->hash_size = 32;
+ queue->hash_size = 64;
if ( ALLOC_ARRAY( queue->buckets, queue->hash_size, FT_ListRec ) )
goto Exit;
- switch ( desc->image_type )
+ switch (FTC_IMAGE_FORMAT(desc->image_type))
{
- case ftc_image_mono:
- clazz = &ftc_mono_image_class;
- break;
+ case ftc_image_format_bitmap:
+ clazz = &ftc_bitmap_image_class;
+ break;
- case ftc_image_grays:
- clazz = &ftc_gray_image_class;
- break;
+ case ftc_image_format_outline:
+ clazz = &ftc_outline_image_class;
+ break;
- case ftc_image_outline:
- clazz = &ftc_outline_image_class;
- break;
-
- case ftc_image_master_outline:
- clazz = &ftc_master_outline_image_class;
- break;
-
- default:
- /* invalid image type! */
- error = FT_Err_Invalid_Argument;
- goto Exit;
+ default:
+ /* invalid image type! */
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
}
queue->clazz = (FTC_Image_Class*)clazz;
@@ -414,6 +288,9 @@
queue->clazz->done_image( queue, inode );
FT_List_Remove( glyphs_lru, lrunode );
+ cache->num_bytes -= queue->clazz->size_image(queue,inode) +
+ sizeof(FTC_ImageNodeRec);
+
FTC_ImageNode_Done( cache, inode );
}
@@ -433,25 +310,29 @@
FTC_Image_Cache cache = queue->cache;
FT_UInt hash_index = glyph_index % queue->hash_size;
FT_List bucket = queue->buckets + hash_index;
- FT_ListNode node, next = 0;
+ FT_ListNode node;
FT_Error error;
FTC_ImageNode inode;
*anode = 0;
- for ( node = bucket->head; node; node = next )
+ for ( node = bucket->head; node; node = node->next )
{
- inode = (FTC_ImageNode)node;
+ FT_UInt gindex;
- if ( FTC_IMAGENODE_GET_GINDEX( inode ) == glyph_index )
+ inode = (FTC_ImageNode)node;
+ gindex = FTC_IMAGENODE_GET_GINDEX(inode);
+
+ if ( gindex == glyph_index )
{
/* we found it! -- move glyph to start of the list */
FT_List_Up( bucket, node );
+ FT_List_Up( &cache->glyphs_lru, FTC_IMAGENODE_TO_LISTNODE( inode ) );
*anode = inode;
return 0;
}
}
-
+
/* we didn't found the glyph image, we will now create a new one */
error = FTC_ImageNode_New( queue->cache, &inode );
if ( error )
@@ -473,7 +354,8 @@
/* insert the node at the start the global LRU glyph list */
FT_List_Insert( &cache->glyphs_lru, FTC_IMAGENODE_TO_LISTNODE( inode ) );
- cache->num_bytes += queue->clazz->size_image(queue,inode);
+ cache->num_bytes += queue->clazz->size_image(queue,inode) +
+ sizeof(FTC_ImageNodeRec);
*anode = inode;
@@ -570,7 +452,7 @@
{
while ( cache->num_bytes > cache->max_bytes )
{
- FT_ListNode cur = cache->glyphs_lru.tail;
+ FT_ListNode cur;
FTC_Image_Queue queue;
FT_UInt glyph_index;
FT_UInt hash_index;
@@ -583,6 +465,7 @@
/* we reached the newly created node (which happens always at the */
/* start of the list) */
+ cur = cache->glyphs_lru.tail;
inode = FTC_LISTNODE_TO_IMAGENODE( cur );
if ( !cur || inode == new_node )
break;
@@ -592,7 +475,8 @@
queue = (FTC_Image_Queue)cache->queues_lru->
nodes[queue_index].root.data;
hash_index = glyph_index % queue->hash_size;
- size = queue->clazz->size_image( queue, inode );
+ size = queue->clazz->size_image( queue, inode ) +
+ sizeof(FTC_ImageNodeRec);
FT_List_Remove( &cache->glyphs_lru, cur );
FT_List_Remove( queue->buckets + hash_index, (FT_ListNode)inode );
@@ -601,9 +485,9 @@
cache->num_bytes -= size;
}
- }
-
+ }
+
FT_EXPORT_DEF( FT_Error ) FTC_Image_Cache_New( FTC_Manager manager,
FT_ULong max_bytes,
FTC_Image_Cache* acache )
@@ -684,11 +568,11 @@
*aglyph = 0;
queue = cache->last_queue;
- if ( !queue ||
- queue->descriptor.size.face_id != desc->size.face_id ||
- queue->descriptor.size.pix_width != desc->size.pix_width ||
- queue->descriptor.size.pix_height != desc->size.pix_height ||
- queue->descriptor.image_type != desc->image_type )
+ if ( !queue ||
+ queue->descriptor.size.face_id != desc->size.face_id ||
+ queue->descriptor.size.pix_width != desc->size.pix_width ||
+ queue->descriptor.size.pix_height != desc->size.pix_height ||
+ queue->descriptor.image_type != desc->image_type )
{
error = FT_Lru_Lookup( cache->queues_lru,
(FT_LruKey)desc,
@@ -702,7 +586,9 @@
if ( error )
goto Exit;
- FTC_Image_Cache_Compress( cache, inode );
+ if (cache->num_bytes > cache->max_bytes)
+ FTC_Image_Cache_Compress( cache, inode );
+
*aglyph = FTC_IMAGENODE_GET_GLYPH( inode );
Exit: