* src/base/ftutil.c: Include FT_INTERNAL_OBJECTS_H.

This commit is contained in:
Werner Lemberg 2005-03-03 23:05:29 +00:00
parent 72393bce3b
commit c1a59318ba
9 changed files with 226 additions and 162 deletions

View File

@ -1,20 +1,6 @@
2005-03-04 David Turner <david@freetype.org>
2005-03-04 Werner Lemberg <wl@gnu.org>
* include/freetype/internal/{ftmemory.h,ftserv.h}: removing
compiler warnings with GCC 3.3 and above...
* include/freetype/internal/ftobjs.h, src/base/ftutil.c (ft_highpow2),
src/pfr/pfrload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h: implement
FT_OPTIMIZE_MEMORY, the kerning table is not loaded into the heap
anymore.
* src/sfnt/ttsbit0.c (tt_sbit_decoder_load_image): Introduce
temporary variable to avoid gcc warning.
(tt_face_load_sbit_image): Mark unused variables with FT_UNUSED.
* include/freetype/config/ftmodule.h: moving the order of drivers to
speed up font loading. the pcf and bdf loaders are still slow and
eat memory like crazy.
* src/base/ftutil.c: Include FT_INTERNAL_OBJECTS_H.
2005-03-03 Werner Lemberg <wl@gnu.org>
@ -48,9 +34,49 @@
* src/truetype/ttgload.c: Include `ttpload.h'.
2005-03-03 David Turner <david@freetype.org>
* include/freetype/internal/ftmemory.h (FT_ALLOC, FT_REALLOC,
FT_QALLOC, FT_QREALLOC) [gcc >= 3.3]: Provide macro versions which
avoid compiler warnings.
(FT_NEW, FT_NEW_ARRAY, FT_RENEW_ARRAY, FT_QNEW, FT_QNEW_ARRAY,
FT_QRENEW_ARRAY, FT_ALLOC_ARRAY, FT_REALLOC_ARRAY): Updated.
* include/freetype/internal/ftserv.h (FT_FACE_FIND_SERVICE,
FT_FACE_FIND_GLOBAL_SERVICE, FT_FACE_LOOKUP_SERVICE) [__cpluscplus]:
Provide macro versions which avoid compiler warnings.
* src/base/ftutil.c (ft_highpow2): New utility function.
* include/freetype/internal/ftobjs.h: Updated.
* src/pfr/pfrload.c (pfr_get_gindex, pfr_compare_kern_pairs,
pfr_sort_kerning_pairs): Don't define if FT_OPTIMIZE_MEMORY is set.
(pfr_phy_font_done): Don't handle `kern_pairs' if FT_OPTIMIZE_MEMORY
is set.
(pfr_phy_font_load): Don't call `pfr_sort_kerning_pairs' if
FT_OPTIMIZE_MEMORY is set.
* src/pfr/pfrobjs.c (pfr_slot_load): Comment out some code which
doesn't work with broken fonts.
(pfr_face_get_kerning) [FT_OPTIMIZE_MEMORY]: Implement.
* src/pfr/pfrtypes.h (PFR_KernItemRec): Optimize member types.
(PFR_NEXT_KPAIR): New macro.
(PFR_PhyFontRec): Don't define `kern_pairs' if FT_OPTIMIZE_MEMORY is
set.
* src/sfnt/ttsbit0.c (tt_sbit_decoder_load_image): Introduce
temporary variable to avoid gcc warning.
(tt_face_load_sbit_image): Mark unused variables with FT_UNUSED.
* src/truetype/ttpload.c (tt_face_load_loca) [FT_OPTIMIZE_MEMORY]:
Remove redundant variable.
* include/freetype/config/ftmodule.h: Moving the order of drivers to
speed up font loading. The PCF and BDF loaders are still slow and
consume far too much memory.
2005-03-03 Werner Lemberg <wl@gnu.org>
* devel/ftoption.h: Updated to recent changes.

View File

@ -369,46 +369,58 @@ FT_BEGIN_HEADER
/* */
/* GCC 3.3 and beyond will generate tons of _stupid_ warnings if we
* don't take special measures.
*/
#if defined(__GNUC__) && ( __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) )
/*
* gcc 3.3 and newer will generate tons of _stupid_ warnings if we
* don't take special measures.
*/
#if defined ( __GNUC__ ) && \
( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 ) )
#define FT_ALLOC( _pointer_, _size_ ) \
({ \
void* _tmp_ = NULL; \
error = FT_MEM_ALLOC( _tmp_, _size_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_REALLOC( _pointer_, _cursize_, _newsize_ ) \
({ \
void* _tmp_ = _pointer_; \
error = FT_MEM_REALLOC( _tmp_, _cursize_, _newsize_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_ALLOC( _pointer_, _size_ ) \
({ \
void* _tmp_ = NULL; \
\
\
error = FT_MEM_ALLOC( _tmp_, _size_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_QALLOC( _pointer_, _size_ ) \
({ \
void* _tmp_; \
error = FT_MEM_QALLOC( _tmp_, _size_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_REALLOC( _pointer_, _cursize_, _newsize_ ) \
({ \
void* _tmp_ = _pointer_; \
\
\
error = FT_MEM_REALLOC( _tmp_, _cursize_, _newsize_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_QREALLOC( _pointer_, _cursize_, _newsize_ ) \
({ \
void* _tmp_ = _pointer_; \
error = FT_MEM_QREALLOC( _tmp_, _cursize_, _newsize_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_QALLOC( _pointer_, _size_ ) \
({ \
void* _tmp_; \
\
\
error = FT_MEM_QALLOC( _tmp_, _size_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#define FT_QREALLOC( _pointer_, _cursize_, _newsize_ ) \
({ \
void* _tmp_ = _pointer_; \
\
\
error = FT_MEM_QREALLOC( _tmp_, _cursize_, _newsize_ ); \
_pointer_ = _tmp_; \
error != 0; \
})
#else /* !GCC || GCC < 3.3 */
#define FT_ALLOC( _pointer_, _size_ ) \
FT_SET_ERROR( FT_MEM_ALLOC( _pointer_, _size_ ) )
@ -423,37 +435,38 @@ FT_BEGIN_HEADER
#endif /* !GCC || GCC < 3.3 */
#define FT_FREE( _pointer_ ) \
FT_MEM_FREE( _pointer_ )
#define FT_NEW( _pointer_ ) \
FT_ALLOC( _pointer_, sizeof(*(_pointer_)) )
#define FT_NEW( _pointer_ ) \
FT_ALLOC( _pointer_, sizeof ( *(_pointer_) ) )
#define FT_NEW_ARRAY( _pointer_, _count_ ) \
FT_ALLOC( _pointer_, sizeof(*(_pointer_))*(_count_) )
#define FT_NEW_ARRAY( _pointer_, _count_ ) \
FT_ALLOC( _pointer_, sizeof ( *(_pointer_) ) * (_count_) )
#define FT_RENEW_ARRAY( _pointer_, _old_, _new_ ) \
FT_REALLOC( _pointer_, sizeof(*(_pointer_))*(_old_), \
sizeof(*(_pointer_))*(_new_) )
#define FT_RENEW_ARRAY( _pointer_, _old_, _new_ ) \
FT_REALLOC( _pointer_, sizeof ( *(_pointer_) ) * (_old_), \
sizeof ( *(_pointer_) ) * (_new_) )
#define FT_QNEW( _pointer_ ) \
FT_QALLOC( _pointer_, sizeof(*(_pointer_)) )
#define FT_QNEW( _pointer_ ) \
FT_QALLOC( _pointer_, sizeof ( *(_pointer_) ) )
#define FT_QNEW_ARRAY( _pointer_, _count_ ) \
FT_QALLOC( _pointer_, sizeof(*(_pointer_))*(_count_) )
#define FT_QNEW_ARRAY( _pointer_, _count_ ) \
FT_QALLOC( _pointer_, sizeof ( *(_pointer_) ) * (_count_) )
#define FT_QRENEW_ARRAY( _pointer_, _old_, _new_ ) \
FT_QREALLOC( _pointer_, sizeof(*(_pointer_))*(_old_), \
sizeof(*(_pointer_))*(_new_) )
#define FT_QRENEW_ARRAY( _pointer_, _old_, _new_ ) \
FT_QREALLOC( _pointer_, sizeof ( *(_pointer_) ) * (_old_), \
sizeof ( *(_pointer_) ) * (_new_) )
#define FT_ALLOC_ARRAY( _pointer_, _count_, _type_ ) \
FT_ALLOC( _pointer_, (_count_)*sizeof( _type_ ) )
#define FT_ALLOC_ARRAY( _pointer_, _count_, _type_ ) \
FT_ALLOC( _pointer_, (_count_) * sizeof ( _type_ ) )
#define FT_REALLOC_ARRAY( _pointer_, _old_, _new_, _type_ ) \
FT_REALLOC( _pointer, (_old_) * sizeof ( _type_ ), \
(_new_) * sizeof ( _type_ ) )
#define FT_REALLOC_ARRAY( _pointer_, _old_, _new_, _type_ ) \
FT_REALLOC( _pointer, (_old_) * sizeof ( _type_ ), \
(_new_) * sizeof ( _type_ ) )
/* */

View File

@ -4,7 +4,7 @@
/* */
/* The FreeType private base classes (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -80,12 +80,14 @@ FT_BEGIN_HEADER
#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )
/* returns the highest power of 2 that is <= value, this correspond to
* the highest bit in a given 32-bit value
*/
/*
* Return the highest power of 2 that is <= value; this correspond to
* the highest bit in a given 32-bit value.
*/
FT_BASE( FT_UInt32 )
ft_highpow2( FT_UInt32 value );
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

View File

@ -4,7 +4,7 @@
/* */
/* The FreeType services (specification only). */
/* */
/* Copyright 2003, 2004 by */
/* Copyright 2003, 2004, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -61,10 +61,11 @@ FT_BEGIN_HEADER
#define FT_FACE_FIND_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
FT_Pointer _tmp_ = NULL; \
FT_Pointer* _pptr_ = (FT_Pointer*)&(ptr); \
\
\
if ( module->clazz->get_interface ) \
_tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
*_pptr_ = _tmp_; \
@ -74,8 +75,8 @@ FT_BEGIN_HEADER
#define FT_FACE_FIND_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
FT_Pointer _tmp_ = NULL; \
FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
FT_Pointer _tmp_ = NULL; \
\
if ( module->clazz->get_interface ) \
_tmp_ = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \
@ -110,10 +111,11 @@ FT_BEGIN_HEADER
#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
FT_Pointer _tmp_; \
FT_Pointer _pptr_ = (FT_Pointer*)&(ptr); \
\
\
_tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
*_pptr_ = _tmp_; \
FT_END_STMNT
@ -122,15 +124,17 @@ FT_BEGIN_HEADER
#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \
FT_Module module = FT_MODULE( FT_FACE( face )->driver ); \
FT_Pointer _tmp_; \
\
\
_tmp_ = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \
ptr = _tmp_; \
FT_END_STMNT
#endif /* !C++ */
/*************************************************************************/
/*************************************************************************/
/***** *****/
@ -229,45 +233,45 @@ FT_BEGIN_HEADER
*/
#ifdef __cplusplus
#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Pointer svc; \
FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \
\
\
svc = FT_FACE(face)->internal->services. service_ ## id; \
if ( svc == FT_SERVICE_UNAVAILABLE ) \
svc = NULL; \
else if ( svc == NULL ) \
{ \
FT_FACE_FIND_SERVICE( face, svc, id ); \
\
FT_FACE(face)->internal->services. service_ ## id = \
(FT_Pointer)( svc != NULL ? svc \
: FT_SERVICE_UNAVAILABLE ); \
} \
*Pptr = svc; \
#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Pointer svc; \
FT_Pointer* Pptr = (FT_Pointer*)&(ptr); \
\
\
svc = FT_FACE( face )->internal->services. service_ ## id; \
if ( svc == FT_SERVICE_UNAVAILABLE ) \
svc = NULL; \
else if ( svc == NULL ) \
{ \
FT_FACE_FIND_SERVICE( face, svc, id ); \
\
FT_FACE( face )->internal->services. service_ ## id = \
(FT_Pointer)( svc != NULL ? svc \
: FT_SERVICE_UNAVAILABLE ); \
} \
*Pptr = svc; \
FT_END_STMNT
#else /* !C++ */
#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Pointer svc; \
\
\
svc = FT_FACE(face)->internal->services. service_ ## id; \
if ( svc == FT_SERVICE_UNAVAILABLE ) \
svc = NULL; \
else if ( svc == NULL ) \
{ \
FT_FACE_FIND_SERVICE( face, svc, id ); \
\
FT_FACE(face)->internal->services. service_ ## id = \
(FT_Pointer)( svc != NULL ? svc \
: FT_SERVICE_UNAVAILABLE ); \
} \
ptr = svc; \
#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \
FT_BEGIN_STMNT \
FT_Pointer svc; \
\
\
svc = FT_FACE( face )->internal->services. service_ ## id; \
if ( svc == FT_SERVICE_UNAVAILABLE ) \
svc = NULL; \
else if ( svc == NULL ) \
{ \
FT_FACE_FIND_SERVICE( face, svc, id ); \
\
FT_FACE( face )->internal->services. service_ ## id = \
(FT_Pointer)( svc != NULL ? svc \
: FT_SERVICE_UNAVAILABLE ); \
} \
ptr = svc; \
FT_END_STMNT
#endif /* !C++ */

View File

@ -283,4 +283,4 @@ FT_END_HEADER
#endif /* __AFHINTS_H__ */
/* END */
/* END */

View File

@ -4,7 +4,7 @@
/* */
/* FreeType utility file for memory and list management (body). */
/* */
/* Copyright 2002, 2004 by */
/* Copyright 2002, 2004, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -19,6 +19,7 @@
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_OBJECTS_H
#include FT_LIST_H
@ -403,12 +404,14 @@
{
FT_UInt32 value2;
/* we simply clear the lowest bit in each iteration. when
* we reach 0, we now that the previous value was our result
*/
/*
* We simply clear the lowest bit in each iteration. When
* we reach 0, we know that the previous value was our result.
*/
for ( ;; )
{
value2 = value & (value-1); /* clear lowest bit */
value2 = value & (value - 1); /* clear lowest bit */
if ( value2 == 0 )
break;

View File

@ -4,7 +4,7 @@
/* */
/* FreeType PFR loader (body). */
/* */
/* Copyright 2002, 2003, 2004 by */
/* Copyright 2002, 2003, 2004, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -610,11 +610,12 @@
#ifndef FT_OPTIMIZE_MEMORY
/*
* 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.
*/
/*
* 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,
@ -671,14 +672,14 @@
FT_UInt count;
/* create kerning pairs array
*/
/* 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
*/
/*
* 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;
@ -732,8 +733,7 @@
FT_FRAME_EXIT();
}
/* sort the resulting array
*/
/* sort the resulting array */
ft_qsort( pairs, count,
sizeof ( PFR_KernPairRec ),
pfr_compare_kern_pairs );
@ -748,8 +748,10 @@
return error;
}
#endif /* !FT_OPTIMIZE_MEMORY */
static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
{
{ 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },

View File

@ -4,7 +4,7 @@
/* */
/* FreeType PFR object methods (body). */
/* */
/* Copyright 2002, 2003, 2004 by */
/* Copyright 2002, 2003, 2004, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -361,7 +361,7 @@
metrics->vertBearingX = 0;
metrics->vertBearingY = 0;
#if 0 /* some fonts seem to be broken here !! */
#if 0 /* some fonts seem to be broken here! */
/* Apply the font matrix, if any. */
/* TODO: Test existing fonts with unusual matrix */
@ -423,16 +423,18 @@
/*************************************************************************/
#ifdef FT_OPTIMIZE_MEMORY
FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning )
{
PFR_Face face = (PFR_Face)pfrface;
FT_Error error = PFR_Err_Ok;
PFR_PhyFont phy_font = &face->phy_font;
FT_UInt32 code1, code2, pair;
PFR_Face face = (PFR_Face)pfrface;
FT_Error error = PFR_Err_Ok;
PFR_PhyFont phy_font = &face->phy_font;
FT_UInt32 code1, code2, pair;
kerning->x = 0;
kerning->y = 0;
@ -450,13 +452,14 @@
code1 = phy_font->chars[glyph1].char_code;
code2 = phy_font->chars[glyph2].char_code;
pair = PFR_KERN_INDEX(code1,code2);
pair = PFR_KERN_INDEX( code1, code2 );
/* now search the list of kerning items */
{
PFR_KernItem item = phy_font->kern_items;
FT_Stream stream = pfrface->stream;
for ( ; item; item = item->next )
{
if ( pair >= item->pair1 && pair <= item->pair2 )
@ -465,28 +468,30 @@
goto Exit;
FoundPair: /* we found an item, now parse it and find the value if any */
if ( FT_STREAM_SEEK( item->offset ) ||
FT_FRAME_ENTER( item->pair_count*item->pair_size ) )
if ( FT_STREAM_SEEK( item->offset ) ||
FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
goto Exit;
{
FT_UInt count = item->pair_count;
FT_UInt size = item->pair_size;
FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count );
FT_UInt probe = power*size;
FT_UInt extra = count - power;
FT_Byte* base = stream->cursor;
FT_Bool twobytes = item->flags & 1;
FT_Byte* p;
FT_UInt32 cpair;
FT_UInt count = item->pair_count;
FT_UInt size = item->pair_size;
FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count );
FT_UInt probe = power * size;
FT_UInt extra = count - power;
FT_Byte* base = stream->cursor;
FT_Bool twobytes = item->flags & 1;
FT_Byte* p;
FT_UInt32 cpair;
if ( extra > 0 )
{
p = base + extra*size;
p = base + extra * size;
if ( twobytes )
cpair = FT_NEXT_ULONG(p);
cpair = FT_NEXT_ULONG( p );
else
cpair = PFR_NEXT_KPAIR(p);
cpair = PFR_NEXT_KPAIR( p );
if ( cpair == pair )
goto Found;
@ -499,10 +504,11 @@
{
probe >>= 1;
p = base + probe;
if ( twobytes )
cpair = FT_NEXT_ULONG(p);
cpair = FT_NEXT_ULONG( p );
else
cpair = PFR_NEXT_KPAIR(p);
cpair = PFR_NEXT_KPAIR( p );
if ( cpair == pair )
goto Found;
@ -512,18 +518,20 @@
}
p = base;
if ( twobytes )
cpair = FT_NEXT_ULONG(p);
cpair = FT_NEXT_ULONG( p );
else
cpair = PFR_NEXT_KPAIR(p);
cpair = PFR_NEXT_KPAIR( p );
if ( cpair == pair )
{
FT_Int value;
Found:
if ( item->flags & 2 )
value = FT_PEEK_SHORT(p);
value = FT_PEEK_SHORT( p );
else
value = p[0];
@ -539,6 +547,7 @@
}
#else /* !FT_OPTIMIZE_MEMORY */
FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
FT_UInt glyph1,
@ -580,6 +589,8 @@
return error;
}
#endif /* !FT_OPTIMIZE_MEMORY */
/* END */

View File

@ -4,7 +4,7 @@
/* */
/* FreeType PFR data structures (specification only). */
/* */
/* Copyright 2002, 2003 by */
/* Copyright 2002, 2003, 2005 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -206,13 +206,16 @@ FT_BEGIN_HEADER
} PFR_KernItemRec;
#define PFR_KERN_INDEX( g1, g2 ) \
( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) )
#define PFR_KERN_PAIR_INDEX( pair ) \
#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 )
#define PFR_NEXT_KPAIR(p) ( p+=2, ((FT_UInt32)p[-2] << 16) | p[-1] )
#define PFR_NEXT_KPAIR( p ) ( p += 2, \
( (FT_UInt32)p[-2] << 16 ) | p[-1] )
typedef struct PFR_KernPairRec_
{