ref: 7d90a4f05caa56fca8e920ed0e84c8d7f2b04e59
parent: 7543f394f77532043c7eeb7f1e028c66da0e4ae6
author: David Turner <[email protected]>
date: Tue Sep 9 16:11:56 EDT 2003
* 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
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2003-09-09 David Turner <[email protected]>
+
+ * 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 <[email protected]>
* src/bdf/bdflib.c (_bdf_readstream): Don't use FT_MEM_COPY but
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -399,7 +399,7 @@
/* 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 */
/*************************************************************************/
--- 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;
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -511,7 +511,6 @@
}
-#if 0
/* load kerning pair data */
FT_CALLBACK_DEF( FT_Error )
@@ -519,88 +518,6 @@
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 )
- pfr_extra_item_load_kerning_pairs( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
PFR_KernItem item;
FT_Error error = 0;
FT_Memory memory = phy_font->memory;
@@ -690,9 +607,141 @@
"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[] =
{
{ 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
@@ -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;
@@ -1007,6 +1057,9 @@
/* save position of bitmap info */
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;
--- 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 )
+ min = 0;
+ max = phy_font->num_kern_pairs;
+
+ while ( min < max )
{
- if ( item->pair1 <= idx && idx <= item->pair2 )
- goto Found_Item;
-
- item = item->next;
- }
-
- /* not found */
- return;
-
- Found_Item:
- {
- /* 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;
}
}
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -209,11 +209,14 @@
#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_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_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 @@
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;