|
|
|
@ -1,20 +1,43 @@ |
|
|
|
|
/***************************************************************************/ |
|
|
|
|
/* */ |
|
|
|
|
/* ftcsbits.c */ |
|
|
|
|
/* */ |
|
|
|
|
/* FreeType sbits manager (body). */ |
|
|
|
|
/* */ |
|
|
|
|
/* Copyright 2000 by */ |
|
|
|
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
|
|
|
/* */ |
|
|
|
|
/* This file is part of the FreeType project, and may only be used, */ |
|
|
|
|
/* modified, and distributed under the terms of the FreeType project */ |
|
|
|
|
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
|
|
|
/* this file you indicate that you have read the license and */ |
|
|
|
|
/* understand and accept it fully. */ |
|
|
|
|
/* */ |
|
|
|
|
/***************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <freetype/cache/ftcsbits.h> |
|
|
|
|
#include <freetype/internal/ftobjs.h> |
|
|
|
|
#include <freetype/internal/ftdebug.h> |
|
|
|
|
#include <freetype/fterrors.h> |
|
|
|
|
|
|
|
|
|
#include <string.h> /* memcmp() */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define FTC_SBITSET_ELEMENT_COUNT 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct FTC_SBitSetRec_ |
|
|
|
|
typedef struct FTC_SBitSetRec_ |
|
|
|
|
{ |
|
|
|
|
FTC_ChunkSetRec root; |
|
|
|
|
FTC_Image_Desc desc; |
|
|
|
|
FTC_ChunkSetRec root; |
|
|
|
|
FTC_Image_Desc desc; |
|
|
|
|
|
|
|
|
|
} FTC_SBitSetRec, *FTC_SBitSet; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct FTC_SBit_CacheRec_ |
|
|
|
|
typedef struct FTC_SBit_CacheRec_ |
|
|
|
|
{ |
|
|
|
|
FTC_Chunk_CacheRec root; |
|
|
|
|
FTC_Chunk_CacheRec root; |
|
|
|
|
|
|
|
|
|
} FTC_SBit_CacheRec; |
|
|
|
|
|
|
|
|
@ -32,10 +55,11 @@ |
|
|
|
|
LOCAL_FUNC_X |
|
|
|
|
void ftc_sbit_chunk_node_destroy( FTC_ChunkNode node ) |
|
|
|
|
{ |
|
|
|
|
FTC_ChunkSet cset = node->cset; |
|
|
|
|
FT_Memory memory = cset->memory; |
|
|
|
|
FT_UInt count = node->num_elements; |
|
|
|
|
FTC_SBit sbit = (FTC_SBit)node->elements; |
|
|
|
|
FTC_ChunkSet cset = node->cset; |
|
|
|
|
FT_Memory memory = cset->memory; |
|
|
|
|
FT_UInt count = node->num_elements; |
|
|
|
|
FTC_SBit sbit = (FTC_SBit)node->elements; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ( ; count > 0; sbit++, count-- ) |
|
|
|
|
FREE( sbit->buffer ); |
|
|
|
@ -45,9 +69,7 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
LOCAL_FUNC_X |
|
|
|
|
FT_Error ftc_bitmap_copy( FT_Memory memory, |
|
|
|
|
FT_Bitmap* source, |
|
|
|
|
FTC_SBit target ) |
|
|
|
@ -56,6 +78,7 @@ |
|
|
|
|
FT_Int pitch = source->pitch; |
|
|
|
|
FT_ULong size; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( pitch < 0 ) |
|
|
|
|
pitch = -pitch; |
|
|
|
|
|
|
|
|
@ -69,25 +92,25 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL_FUNC_X |
|
|
|
|
FT_Error ftc_sbit_chunk_node_new( FTC_ChunkSet cset, |
|
|
|
|
FT_UInt index, |
|
|
|
|
FTC_ChunkNode *anode ) |
|
|
|
|
FT_Error ftc_sbit_chunk_node_new( FTC_ChunkSet cset, |
|
|
|
|
FT_UInt index, |
|
|
|
|
FTC_ChunkNode* anode ) |
|
|
|
|
{ |
|
|
|
|
FT_Error error; |
|
|
|
|
FT_Memory memory = cset->memory; |
|
|
|
|
FTC_SBitSet sbitset = (FTC_SBitSet)cset; |
|
|
|
|
FTC_ChunkNode node = 0; |
|
|
|
|
FT_Face face; |
|
|
|
|
FT_Size size; |
|
|
|
|
FT_Error error; |
|
|
|
|
FT_Memory memory = cset->memory; |
|
|
|
|
FTC_SBitSet sbitset = (FTC_SBitSet)cset; |
|
|
|
|
FTC_ChunkNode node = 0; |
|
|
|
|
FT_Face face; |
|
|
|
|
FT_Size size; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate node */ |
|
|
|
|
if ( ALLOC( node, sizeof ( *node ) ) ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
/* init its inner fields */ |
|
|
|
|
/* initialize its inner fields */ |
|
|
|
|
error = FTC_ChunkNode_Init( node, cset, index, 1 ); |
|
|
|
|
if (error) |
|
|
|
|
if ( error ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
/* we will now load all glyph images for this chunk */ |
|
|
|
@ -96,86 +119,86 @@ |
|
|
|
|
&face, &size ); |
|
|
|
|
if ( !error ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt glyph_index = index * cset->element_count; |
|
|
|
|
FT_UInt load_flags = FT_LOAD_DEFAULT; |
|
|
|
|
FT_UInt image_type = sbitset->desc.image_type; |
|
|
|
|
FT_UInt count = node->num_elements; |
|
|
|
|
FTC_SBit sbit = (FTC_SBit)node->elements; |
|
|
|
|
FT_UInt glyph_index = index * cset->element_count; |
|
|
|
|
FT_UInt load_flags = FT_LOAD_DEFAULT; |
|
|
|
|
FT_UInt image_type = sbitset->desc.image_type; |
|
|
|
|
FT_UInt count = node->num_elements; |
|
|
|
|
FTC_SBit sbit = (FTC_SBit)node->elements; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* determine load flags, depending on the font description's */ |
|
|
|
|
/* image type.. */ |
|
|
|
|
{ |
|
|
|
|
if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap ) |
|
|
|
|
{ |
|
|
|
|
if ( image_type & ftc_image_flag_monochrome ) |
|
|
|
|
load_flags |= FT_LOAD_MONOCHROME; |
|
|
|
|
/* image type */ |
|
|
|
|
|
|
|
|
|
/* disable embedded bitmaps loading if necessary */ |
|
|
|
|
if ( image_type & ftc_image_flag_no_sbits ) |
|
|
|
|
load_flags |= FT_LOAD_NO_BITMAP; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
FT_ERROR(( "FTC_SBit_Cache: cannot load scalable glyphs in a" |
|
|
|
|
" sbit cache, please check your arguments !!\n" )); |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap ) |
|
|
|
|
{ |
|
|
|
|
if ( image_type & ftc_image_flag_monochrome ) |
|
|
|
|
load_flags |= FT_LOAD_MONOCHROME; |
|
|
|
|
|
|
|
|
|
/* always render glyphs to bitmaps */ |
|
|
|
|
load_flags |= FT_LOAD_RENDER; |
|
|
|
|
/* disable embedded bitmaps loading if necessary */ |
|
|
|
|
if ( image_type & ftc_image_flag_no_sbits ) |
|
|
|
|
load_flags |= FT_LOAD_NO_BITMAP; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
FT_ERROR(( "FTC_SBit_Cache: cannot load scalable glyphs in an" |
|
|
|
|
" sbit cache, please check your arguments!\n" )); |
|
|
|
|
error = FT_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( image_type & ftc_image_flag_unhinted ) |
|
|
|
|
load_flags |= FT_LOAD_NO_HINTING; |
|
|
|
|
/* always render glyphs to bitmaps */ |
|
|
|
|
load_flags |= FT_LOAD_RENDER; |
|
|
|
|
|
|
|
|
|
if ( image_type & ftc_image_flag_autohinted ) |
|
|
|
|
load_flags |= FT_LOAD_FORCE_AUTOHINT; |
|
|
|
|
} |
|
|
|
|
if ( image_type & ftc_image_flag_unhinted ) |
|
|
|
|
load_flags |= FT_LOAD_NO_HINTING; |
|
|
|
|
|
|
|
|
|
if ( image_type & ftc_image_flag_autohinted ) |
|
|
|
|
load_flags |= FT_LOAD_FORCE_AUTOHINT; |
|
|
|
|
|
|
|
|
|
/* load a chunk of small bitmaps in a row */ |
|
|
|
|
for ( ; count > 0; count--, glyph_index++, sbit++ ) |
|
|
|
|
{ |
|
|
|
|
/* by default, indicates a "missing" glyph */ |
|
|
|
|
/* by default, indicates a `missing' glyph */ |
|
|
|
|
sbit->buffer = 0; |
|
|
|
|
|
|
|
|
|
error = FT_Load_Glyph( face, glyph_index, load_flags ); |
|
|
|
|
if (!error) |
|
|
|
|
if ( !error ) |
|
|
|
|
{ |
|
|
|
|
FT_Int temp; |
|
|
|
|
FT_GlyphSlot slot = face->glyph; |
|
|
|
|
FT_Bitmap* bitmap = &slot->bitmap; |
|
|
|
|
FT_Int xadvance, yadvance; |
|
|
|
|
|
|
|
|
|
/* check that our values fit in 8-bit containers !! */ |
|
|
|
|
/* if this is not the case, our bitmap is too large */ |
|
|
|
|
/* and we will leave it as "missing" with sbit.buffer = 0 */ |
|
|
|
|
|
|
|
|
|
#define CHECK_CHAR(d) ( temp = (FT_Char)d, temp == d ) |
|
|
|
|
#define CHECK_BYTE(d) ( temp = (FT_Byte)d, temp == d ) |
|
|
|
|
/* check that our values fit into 8-bit containers! */ |
|
|
|
|
/* If this is not the case, our bitmap is too large */ |
|
|
|
|
/* and we will leave it as `missing' with sbit.buffer = 0 */ |
|
|
|
|
|
|
|
|
|
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) |
|
|
|
|
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) |
|
|
|
|
|
|
|
|
|
/* FIXME: add support for vertical layouts maybe.. */ |
|
|
|
|
/* XXX: FIXME: add support for vertical layouts maybe */ |
|
|
|
|
|
|
|
|
|
/* horizontal advance in pixels */ |
|
|
|
|
xadvance = (slot->metrics.horiAdvance+32) >> 6; |
|
|
|
|
yadvance = (slot->metrics.vertAdvance+32) >> 6; |
|
|
|
|
/* horizontal advance in pixels */ |
|
|
|
|
xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6; |
|
|
|
|
yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6; |
|
|
|
|
|
|
|
|
|
if ( CHECK_BYTE ( bitmap->rows ) && |
|
|
|
|
CHECK_BYTE ( bitmap->width ) && |
|
|
|
|
CHECK_CHAR ( bitmap->pitch ) && |
|
|
|
|
CHECK_CHAR ( slot->bitmap_left ) && |
|
|
|
|
CHECK_CHAR ( slot->bitmap_top ) && |
|
|
|
|
CHECK_CHAR ( xadvance ) && |
|
|
|
|
CHECK_CHAR ( yadvance ) ) |
|
|
|
|
if ( CHECK_BYTE( bitmap->rows ) && |
|
|
|
|
CHECK_BYTE( bitmap->width ) && |
|
|
|
|
CHECK_CHAR( bitmap->pitch ) && |
|
|
|
|
CHECK_CHAR( slot->bitmap_left ) && |
|
|
|
|
CHECK_CHAR( slot->bitmap_top ) && |
|
|
|
|
CHECK_CHAR( xadvance ) && |
|
|
|
|
CHECK_CHAR( yadvance ) ) |
|
|
|
|
{ |
|
|
|
|
sbit->width = (FT_Byte) bitmap->width; |
|
|
|
|
sbit->height = (FT_Byte) bitmap->rows; |
|
|
|
|
sbit->pitch = (FT_Char) bitmap->pitch; |
|
|
|
|
sbit->left = (FT_Char) slot->bitmap_left; |
|
|
|
|
sbit->top = (FT_Char) slot->bitmap_top; |
|
|
|
|
sbit->xadvance = (FT_Char) xadvance; |
|
|
|
|
sbit->yadvance = (FT_Char) yadvance; |
|
|
|
|
sbit->format = (FT_Byte) bitmap->pixel_mode; |
|
|
|
|
sbit->width = (FT_Byte)bitmap->width; |
|
|
|
|
sbit->height = (FT_Byte)bitmap->rows; |
|
|
|
|
sbit->pitch = (FT_Char)bitmap->pitch; |
|
|
|
|
sbit->left = (FT_Char)slot->bitmap_left; |
|
|
|
|
sbit->top = (FT_Char)slot->bitmap_top; |
|
|
|
|
sbit->xadvance = (FT_Char)xadvance; |
|
|
|
|
sbit->yadvance = (FT_Char)yadvance; |
|
|
|
|
sbit->format = (FT_Byte)bitmap->pixel_mode; |
|
|
|
|
|
|
|
|
|
/* grab the bitmap when possible */ |
|
|
|
|
if ( slot->flags & ft_glyph_own_bitmap ) |
|
|
|
@ -185,15 +208,15 @@ |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* copy the bitmap into a new buffer - ignore error */ |
|
|
|
|
/* copy the bitmap into a new buffer -- ignore error */ |
|
|
|
|
ftc_bitmap_copy( memory, bitmap, sbit ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ignore the errors that might have occured there */ |
|
|
|
|
/* we recognize unloaded glyphs with "sbit.buffer == 0" */ |
|
|
|
|
/* ignore the errors that might have occurred -- */ |
|
|
|
|
/* we recognize unloaded glyphs with `sbit.buffer == 0' */ |
|
|
|
|
error = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -205,12 +228,13 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*anode = node; |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* this function is important because it is both part of */ |
|
|
|
|
/* a FTC_ChunkSet_Class and a FTC_CacheNode_Class */ |
|
|
|
|
/* an FTC_ChunkSet_Class and an FTC_CacheNode_Class */ |
|
|
|
|
/* */ |
|
|
|
|
LOCAL_FUNC_X |
|
|
|
|
FT_ULong ftc_sbit_chunk_node_size( FTC_ChunkNode node ) |
|
|
|
@ -221,15 +245,18 @@ |
|
|
|
|
FT_Int pitch; |
|
|
|
|
FTC_SBit sbit = (FTC_SBit)node->elements; |
|
|
|
|
|
|
|
|
|
size = sizeof (*node); /* the node itself */ |
|
|
|
|
size += cset->element_count * sizeof(FTC_SBitRec); /* the sbit recors */ |
|
|
|
|
|
|
|
|
|
/* the node itself */ |
|
|
|
|
size = sizeof ( *node ); |
|
|
|
|
/* the sbit records */ |
|
|
|
|
size += cset->element_count * sizeof ( FTC_SBitRec ); |
|
|
|
|
|
|
|
|
|
for ( ; count > 0; count--, sbit++ ) |
|
|
|
|
{ |
|
|
|
|
if (sbit->buffer) |
|
|
|
|
if ( sbit->buffer ) |
|
|
|
|
{ |
|
|
|
|
pitch = sbit->pitch; |
|
|
|
|
if (pitch < 0) |
|
|
|
|
if ( pitch < 0 ) |
|
|
|
|
pitch = -pitch; |
|
|
|
|
|
|
|
|
|
/* add the size of a given glyph image */ |
|
|
|
@ -257,25 +284,26 @@ |
|
|
|
|
FT_Error error; |
|
|
|
|
FT_Face face; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cset->element_count = FTC_SBITSET_ELEMENT_COUNT; |
|
|
|
|
cset->element_size = sizeof(FTC_SBitRec); |
|
|
|
|
cset->element_size = sizeof ( FTC_SBitRec ); |
|
|
|
|
|
|
|
|
|
/* lookup the FT_Face to obtain the number of glyphs */ |
|
|
|
|
error = FTC_Manager_Lookup_Face( cset->manager, |
|
|
|
|
desc->font.face_id, &face ); |
|
|
|
|
if (!error) |
|
|
|
|
if ( !error ) |
|
|
|
|
cset->element_max = face->num_glyphs; |
|
|
|
|
|
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL_FUNC_X |
|
|
|
|
FT_Error ftc_sbit_chunk_set_init( FTC_SBitSet sset, |
|
|
|
|
FTC_Image_Desc* type ) |
|
|
|
|
{ |
|
|
|
|
sset->desc = *type; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -292,14 +320,14 @@ |
|
|
|
|
{ |
|
|
|
|
sizeof( FTC_SBitSetRec ), |
|
|
|
|
|
|
|
|
|
(FTC_ChunkSet_InitFunc) ftc_sbit_chunk_set_init, |
|
|
|
|
(FTC_ChunkSet_DoneFunc) 0, |
|
|
|
|
(FTC_ChunkSet_CompareFunc) ftc_sbit_chunk_set_compare, |
|
|
|
|
(FTC_ChunkSet_SizesFunc) ftc_sbit_chunk_set_sizes, |
|
|
|
|
(FTC_ChunkSet_InitFunc) ftc_sbit_chunk_set_init, |
|
|
|
|
(FTC_ChunkSet_DoneFunc) 0, |
|
|
|
|
(FTC_ChunkSet_CompareFunc) ftc_sbit_chunk_set_compare, |
|
|
|
|
(FTC_ChunkSet_SizesFunc) ftc_sbit_chunk_set_sizes, |
|
|
|
|
|
|
|
|
|
(FTC_ChunkSet_NewNodeFunc) ftc_sbit_chunk_node_new, |
|
|
|
|
(FTC_ChunkSet_SizeNodeFunc) ftc_sbit_chunk_node_size, |
|
|
|
|
(FTC_ChunkSet_DestroyNodeFunc) ftc_sbit_chunk_node_destroy |
|
|
|
|
(FTC_ChunkSet_NewNodeFunc) ftc_sbit_chunk_node_new, |
|
|
|
|
(FTC_ChunkSet_SizeNodeFunc) ftc_sbit_chunk_node_size, |
|
|
|
|
(FTC_ChunkSet_DestroyNodeFunc)ftc_sbit_chunk_node_destroy |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -316,16 +344,15 @@ |
|
|
|
|
{ |
|
|
|
|
{ |
|
|
|
|
sizeof( FTC_SBit_CacheRec ), |
|
|
|
|
(FTC_Cache_InitFunc) FTC_Chunk_Cache_Init, |
|
|
|
|
(FTC_Cache_DoneFunc) FTC_Chunk_Cache_Done |
|
|
|
|
(FTC_Cache_InitFunc)FTC_Chunk_Cache_Init, |
|
|
|
|
(FTC_Cache_DoneFunc)FTC_Chunk_Cache_Done |
|
|
|
|
}, |
|
|
|
|
(FTC_ChunkSet_Class*) &ftc_sbit_chunk_set_class |
|
|
|
|
(FTC_ChunkSet_Class*)&ftc_sbit_chunk_set_class |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_EXPORT_FUNC( FT_Error ) |
|
|
|
|
FTC_SBit_Cache_New( FTC_Manager manager, |
|
|
|
|
FTC_SBit_Cache* acache ) |
|
|
|
|
FT_EXPORT_FUNC( FT_Error ) FTC_SBit_Cache_New( FTC_Manager manager, |
|
|
|
|
FTC_SBit_Cache* acache ) |
|
|
|
|
{ |
|
|
|
|
return FTC_Manager_Register_Cache( |
|
|
|
|
manager, |
|
|
|
@ -334,11 +361,10 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_EXPORT_DEF( FT_Error ) |
|
|
|
|
FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache, |
|
|
|
|
FTC_Image_Desc* desc, |
|
|
|
|
FT_UInt gindex, |
|
|
|
|
FTC_SBit *asbit ) |
|
|
|
|
FT_EXPORT_DEF( FT_Error ) FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache, |
|
|
|
|
FTC_Image_Desc* desc, |
|
|
|
|
FT_UInt gindex, |
|
|
|
|
FTC_SBit* asbit ) |
|
|
|
|
{ |
|
|
|
|
FT_Error error; |
|
|
|
|
FTC_ChunkSet cset; |
|
|
|
@ -355,9 +381,10 @@ |
|
|
|
|
if ( !cache || !asbit ) |
|
|
|
|
return FT_Err_Invalid_Argument; |
|
|
|
|
|
|
|
|
|
*asbit = 0; |
|
|
|
|
cset = cache->root.last_cset; |
|
|
|
|
sset = (FTC_SBitSet)cset; |
|
|
|
|
*asbit = 0; |
|
|
|
|
cset = cache->root.last_cset; |
|
|
|
|
sset = (FTC_SBitSet)cset; |
|
|
|
|
|
|
|
|
|
if ( !cset || memcmp( &sset->desc, desc, sizeof ( *desc ) ) ) |
|
|
|
|
{ |
|
|
|
|
error = FT_Lru_Lookup( cache->root.csets_lru, |
|
|
|
@ -388,3 +415,5 @@ |
|
|
|
|
return error; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* END */ |
|
|
|
|