From b0b1ea3feac634877963a4005898fabb8d05a568 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 9 Sep 2003 20:11:56 +0000 Subject: [PATCH] * src/base/ftpfr.c, src/pfr/pfrtypes.h, src/pfr/pfrload.c, src/pfr/pfrobjs.c: fixing PFR kerning support. The tables within the font file contain (charcode,charcode) kerning pairs, we need to convert them to (gindex,gindex) ! * include/freetype/ftoption.h: commenting out the macro TT_CONFIG_OPTION_BYTECODE_INTERPRETER --- ChangeLog | 10 ++ include/freetype/config/ftoption.h | 2 +- src/base/ftpfr.c | 2 +- src/pfr/pfrload.c | 221 ++++++++++++++++++----------- src/pfr/pfrobjs.c | 79 +++-------- src/pfr/pfrtypes.h | 12 +- 6 files changed, 175 insertions(+), 151 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62aca83ac..8e766211d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-09-09 David Turner + + * src/base/ftpfr.c, src/pfr/pfrtypes.h, src/pfr/pfrload.c, + src/pfr/pfrobjs.c: fixing PFR kerning support. The tables within + the font file contain (charcode,charcode) kerning pairs, we need + to convert them to (gindex,gindex) ! + + * include/freetype/ftoption.h: commenting out the macro + TT_CONFIG_OPTION_BYTECODE_INTERPRETER + 2003-08-31 Manish Singh * src/bdf/bdflib.c (_bdf_readstream): Don't use FT_MEM_COPY but diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h index 77540b28f..3581caaa6 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -399,7 +399,7 @@ FT_BEGIN_HEADER /* Do not #undef this macro here, since the build system might */ /* define it for certain configurations only. */ /* */ -#undef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ /*************************************************************************/ diff --git a/src/base/ftpfr.c b/src/base/ftpfr.c index d9594cb78..a23dcab0b 100644 --- a/src/base/ftpfr.c +++ b/src/base/ftpfr.c @@ -37,7 +37,7 @@ if ( name[0] == 'p' && name[1] == 'f' && name[2] == 'r' && - name[4] == 0 ) + name[3] == 0 ) { *aservice = (FT_PFR_Service) module->clazz->module_interface; error = 0; diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c index e92ead95b..1ef58460e 100644 --- a/src/pfr/pfrload.c +++ b/src/pfr/pfrload.c @@ -511,89 +511,6 @@ } -#if 0 - - /* load kerning pair data */ - FT_CALLBACK_DEF( FT_Error ) - pfr_extra_item_load_kerning_pairs( FT_Byte* p, - FT_Byte* limit, - PFR_PhyFont phy_font ) - { - FT_Int count; - FT_UShort base_adj; - FT_UInt flags; - FT_UInt num_pairs; - PFR_KernPair pairs; - FT_Error error = 0; - FT_Memory memory = phy_font->memory; - - - /* allocate a new kerning item */ - /* XXX: there may be multiple extra items for kerning */ - if ( phy_font->kern_pairs != NULL ) - goto Exit; - - FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" )); - - PFR_CHECK( 4 ); - - num_pairs = PFR_NEXT_BYTE( p ); - base_adj = PFR_NEXT_SHORT( p ); - flags = PFR_NEXT_BYTE( p ); - -#ifndef PFR_CONFIG_NO_CHECKS - count = 3; - - if ( flags & PFR_KERN_2BYTE_CHAR ) - count += 2; - - if ( flags & PFR_KERN_2BYTE_ADJ ) - count += 1; - - PFR_CHECK( num_pairs * count ); -#endif - - if ( FT_NEW_ARRAY( pairs, num_pairs ) ) - goto Exit; - - phy_font->num_kern_pairs = num_pairs; - phy_font->kern_pairs = pairs; - - for (count = num_pairs ; count > 0; count--, pairs++ ) - { - if ( flags & PFR_KERN_2BYTE_CHAR ) - { - pairs->glyph1 = PFR_NEXT_USHORT( p ); - pairs->glyph2 = PFR_NEXT_USHORT( p ); - } - else - { - pairs->glyph1 = PFR_NEXT_BYTE( p ); - pairs->glyph2 = PFR_NEXT_BYTE( p ); - } - - if ( flags & PFR_KERN_2BYTE_ADJ ) - pairs->kerning.x = base_adj + PFR_NEXT_SHORT( p ); - else - pairs->kerning.x = base_adj + PFR_NEXT_INT8( p ); - - pairs->kerning.y = 0; - - FT_TRACE2(( "kerning %d <-> %d : %ld\n", - pairs->glyph1, pairs->glyph2, pairs->kerning.x )); - } - - Exit: - return error; - - Too_Short: - error = PFR_Err_Invalid_Table; - FT_ERROR(( "pfr_extra_item_load_kerning_pairs: " - "invalid kerning pairs table\n" )); - goto Exit; - } - -#else /* 0 */ /* load kerning pair data */ FT_CALLBACK_DEF( FT_Error ) @@ -690,7 +607,139 @@ "invalid kerning pairs table\n" )); goto Exit; } -#endif /* 0 */ + + + /* the kerning data embedded in a PFR font are (charcode,charcode) + * pairs, we need to translate them to (gindex,gindex) and sort + * the resulting array + */ + static FT_UInt + pfr_get_gindex( PFR_Char chars, + FT_UInt count, + FT_UInt charcode ) + { + FT_UInt min = 0; + FT_UInt max = count; + + while ( min < max ) + { + FT_UInt mid = (min+max) >> 1; + PFR_Char c = chars + mid; + + if ( c->char_code == charcode ) + return mid + 1; + + if ( c->char_code < charcode ) + min = mid + 1; + else + max = mid; + } + return 0; + } + + + FT_CALLBACK_DEF( int ) + pfr_compare_kern_pairs( const void* pair1, + const void* pair2 ) + { + FT_UInt32 p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 ); + FT_UInt32 p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 ); + + if ( p1 < p2 ) + return -1; + if ( p1 > p2 ) + return 1; + return 0; + } + + + static FT_Error + pfr_sort_kerning_pairs( FT_Stream stream, + PFR_PhyFont phy_font ) + { + FT_Error error; + FT_Memory memory = stream->memory; + PFR_KernPair pairs; + PFR_KernItem item; + PFR_Char chars = phy_font->chars; + FT_UInt num_chars = phy_font->num_chars; + FT_UInt count; + + /* create kerning pairs array + */ + if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) ) + goto Exit; + + /* load all kerning items into the array, + * converting character codes into glyph indices + */ + pairs = phy_font->kern_pairs; + item = phy_font->kern_items; + count = 0; + + for ( ; item; item = item->next ) + { + FT_UInt limit = count + item->pair_count; + FT_Byte* p; + + if ( limit > phy_font->num_kern_pairs ) + { + error = PFR_Err_Invalid_Table; + goto Exit; + } + + if ( FT_STREAM_SEEK( item->offset ) || + FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) + goto Exit; + + p = stream->cursor; + + for ( ; count < limit; count++ ) + { + PFR_KernPair pair = pairs + count; + FT_UInt char1, char2; + FT_Int kerning; + + if ( item->flags & PFR_KERN_2BYTE_CHAR ) + { + char1 = FT_NEXT_USHORT( p ); + char2 = FT_NEXT_USHORT( p ); + } + else + { + char1 = FT_NEXT_BYTE( p ); + char2 = FT_NEXT_BYTE( p ); + } + + if ( item->flags & PFR_KERN_2BYTE_ADJ ) + kerning = item->base_adj + FT_NEXT_SHORT( p ); + else + kerning = item->base_adj + FT_NEXT_CHAR( p ); + + pair->glyph1 = pfr_get_gindex( chars, num_chars, char1 ); + pair->glyph2 = pfr_get_gindex( chars, num_chars, char2 ); + pair->kerning = kerning; + } + + FT_FRAME_EXIT(); + } + + /* sort the resulting array + */ + ft_qsort( pairs, count, + sizeof ( PFR_KernPairRec ), + pfr_compare_kern_pairs ); + + Exit: + if ( error ) + { + /* disable kerning data in case of error + */ + phy_font->num_kern_pairs = 0; + } + + return error; + } static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = @@ -770,6 +819,7 @@ FT_FREE( phy_font->blue_values ); phy_font->num_blue_values = 0; + FT_FREE( phy_font->kern_pairs ); { PFR_KernItem item, next; @@ -1008,6 +1058,9 @@ phy_font->bct_offset = FT_STREAM_POS(); phy_font->cursor = NULL; + /* now sort kerning pairs */ + error = pfr_sort_kerning_pairs( stream, phy_font ); + Exit: return error; diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c index 402db95d3..e96b4846f 100644 --- a/src/pfr/pfrobjs.c +++ b/src/pfr/pfrobjs.c @@ -419,77 +419,34 @@ { FT_Error error = PFR_Err_Ok; PFR_PhyFont phy_font = &face->phy_font; - PFR_KernItem item = phy_font->kern_items; + PFR_KernPair pairs = phy_font->kern_pairs; FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 ); + FT_UInt min, max; FT_UNUSED( error ); /* just needed as syntactical sugar */ - kerning->x = 0; kerning->y = 0; - /* find the kerning item containing our pair */ - while ( item ) - { - if ( item->pair1 <= idx && idx <= item->pair2 ) - goto Found_Item; - - item = item->next; - } - - /* not found */ - return; - - Found_Item: + min = 0; + max = phy_font->num_kern_pairs; + + while ( min < max ) { - /* perform simply binary search within the item */ - FT_UInt min, mid, max; - FT_Stream stream = face->root.stream; - FT_Byte* p; - - - if ( FT_STREAM_SEEK( item->offset ) || - FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) - return; - - min = 0; - max = item->pair_count; - while ( min < max ) + FT_UInt mid = (min+max) >> 1; + PFR_KernPair pair = pairs + mid; + FT_UInt32 pidx = PFR_KERN_PAIR_INDEX( pair ); + + if ( pidx == idx ) { - FT_UInt char1, char2, charcode; - - - mid = ( min + max ) >> 1; - p = stream->cursor + mid*item->pair_size; - - if ( item->flags & PFR_KERN_2BYTE_CHAR ) - { - char1 = FT_NEXT_USHORT( p ); - char2 = FT_NEXT_USHORT( p ); - } - else - { - char1 = FT_NEXT_USHORT( p ); - char2 = FT_NEXT_USHORT( p ); - } - charcode = PFR_KERN_INDEX( char1, char2 ); - - if ( idx == charcode ) - { - if ( item->flags & PFR_KERN_2BYTE_ADJ ) - kerning->x = item->base_adj + FT_NEXT_SHORT( p ); - else - kerning->x = item->base_adj + FT_NEXT_CHAR( p ); - - break; - } - if ( idx > charcode ) - min = mid + 1; - else - max = mid; + kerning->x = pair->kerning; + break; } - - FT_FRAME_EXIT(); + + if ( pidx < idx ) + min = mid+1; + else + max = mid; } } diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h index 21b4e3d2e..a10a2b26c 100644 --- a/src/pfr/pfrtypes.h +++ b/src/pfr/pfrtypes.h @@ -209,11 +209,14 @@ FT_BEGIN_HEADER #define PFR_KERN_INDEX( g1, g2 ) \ ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) ) +#define PFR_KERN_PAIR_INDEX( pair ) \ + PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 ) + typedef struct PFR_KernPairRec_ { FT_UInt glyph1; FT_UInt glyph2; - FT_Vector kerning; + FT_Int kerning; } PFR_KernPairRec, *PFR_KernPair; @@ -230,7 +233,7 @@ FT_BEGIN_HEADER FT_BBox bbox; FT_UInt flags; FT_UInt standard_advance; - + FT_Int ascent; /* optional, bbox.yMax if not present */ FT_Int descent; /* optional, bbox.yMin if not present */ FT_Int leading; /* optional, 0 if not present */ @@ -258,6 +261,7 @@ FT_BEGIN_HEADER FT_UInt num_kern_pairs; PFR_KernItem kern_items; PFR_KernItem* kern_items_tail; + PFR_KernPair kern_pairs; /* not part of the spec, but used during load */ FT_UInt32 bct_offset; @@ -281,8 +285,8 @@ FT_BEGIN_HEADER typedef enum PFR_KernFlags_ { - PFR_KERN_2BYTE_ADJ = 0x01, - PFR_KERN_2BYTE_CHAR = 0x02 + PFR_KERN_2BYTE_CHAR = 0x01, + PFR_KERN_2BYTE_ADJ = 0x02 } PFR_KernFlags;