* docs/CHANGES: Updated.

FreeType now can read kerning values from PFM files.

* src/type1/t1afm.c (T1_Done_AFM): Renamed to...
(T1_Done_Metrics): This.
Update all callers.
(T1_Read_AFM): Make it static.
Don't enter and leave a frame.
(LITTLE_ENDIAN_USHORT, LITTLE_ENDIAN_UINT): New macros.
(T1_Read_PFM): New function.
(T1_Read_Metrics): New higher-level function to be used instead of
T1Read_AFM.
Update all callers.
This commit is contained in:
Werner Lemberg 2004-08-02 05:38:33 +00:00
parent 3273a99160
commit d232f59383
6 changed files with 218 additions and 13 deletions

View File

@ -1,3 +1,22 @@
2004-08-01 Werner Lemberg <wl@gnu.org>
* docs/CHANGES: Updated.
2004-08-01 George Williams <gww@silcom.com>
FreeType now can read kerning values from PFM files.
* src/type1/t1afm.c (T1_Done_AFM): Renamed to...
(T1_Done_Metrics): This.
Update all callers.
(T1_Read_AFM): Make it static.
Don't enter and leave a frame.
(LITTLE_ENDIAN_USHORT, LITTLE_ENDIAN_UINT): New macros.
(T1_Read_PFM): New function.
(T1_Read_Metrics): New higher-level function to be used instead of
T1Read_AFM.
Update all callers.
2004-07-31 Werner Lemberg <wl@gnu.org> 2004-07-31 Werner Lemberg <wl@gnu.org>
* src/pcf/pcfread (pcf_load_font), src/bdf/bdfdrivr.c * src/pcf/pcfread (pcf_load_font), src/bdf/bdfdrivr.c

View File

@ -1,3 +1,25 @@
LATEST CHANGES BETWEEN 2.1.10 and 2.1.9
I. IMPORTANT BUG FIXES
- The size comparison for BDF and PCF files could fail sometimes.
- Some CFF files were still not loaded correctly. Patch from
Derek Noonburg.
- The stroker still had some serious bugs.
II. IMPORTANT CHANGES
- George Williams contributed code to read kerning data from PFM
files.
- FreeType now uses the TT_NAME_ID_PREFERRED_FAMILY and
TT_NAME_ID_PREFERRED_SUBFAMILY strings (if available) for
setting family and style in SFNT fonts (patch from Kornfeld
Eliyahu Peter).
LATEST CHANGES BETWEEN 2.1.9 and 2.1.8 LATEST CHANGES BETWEEN 2.1.9 and 2.1.8

View File

@ -33,8 +33,8 @@
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
T1_Done_AFM( FT_Memory memory, T1_Done_Metrics( FT_Memory memory,
T1_AFM* afm ) T1_AFM* afm )
{ {
FT_FREE( afm->kern_pairs ); FT_FREE( afm->kern_pairs );
afm->num_pairs = 0; afm->num_pairs = 0;
@ -153,11 +153,11 @@
/* parse an AFM file -- for now, only read the kerning pairs */ /* parse an AFM file -- for now, only read the kerning pairs */
FT_LOCAL_DEF( FT_Error ) static FT_Error
T1_Read_AFM( FT_Face t1_face, T1_Read_AFM( FT_Face t1_face,
FT_Stream stream ) FT_Stream stream )
{ {
FT_Error error; FT_Error error = T1_Err_Ok;
FT_Memory memory = stream->memory; FT_Memory memory = stream->memory;
FT_Byte* start; FT_Byte* start;
FT_Byte* limit; FT_Byte* limit;
@ -168,9 +168,6 @@
T1_AFM* afm = 0; T1_AFM* afm = 0;
if ( FT_FRAME_ENTER( stream->size ) )
return error;
start = (FT_Byte*)stream->cursor; start = (FT_Byte*)stream->cursor;
limit = (FT_Byte*)stream->limit; limit = (FT_Byte*)stream->limit;
p = start; p = start;
@ -233,6 +230,173 @@
if ( error ) if ( error )
FT_FREE( afm ); FT_FREE( afm );
return error;
}
#define LITTLE_ENDIAN_USHORT( p ) (FT_UShort)( ( (p)[0] ) | \
( (p)[1] << 8 ) )
#define LITTLE_ENDIAN_UINT( p ) (FT_UInt)( ( (p)[0] ) | \
( (p)[1] << 8 ) | \
( (p)[2] << 16 ) | \
( (p)[3] << 24 ) )
/* parse a PFM file -- for now, only read the kerning pairs */
static FT_Error
T1_Read_PFM( FT_Face t1_face,
FT_Stream stream )
{
FT_Error error = T1_Err_Ok;
FT_Memory memory = stream->memory;
FT_Byte* start;
FT_Byte* limit;
FT_Byte* p;
FT_Int kern_count = 0;
T1_Kern_Pair* pair;
T1_AFM* afm = 0;
FT_Int width_table_length;
FT_CharMap oldcharmap;
FT_CharMap charmap;
FT_Int n;
start = (FT_Byte*)stream->cursor;
limit = (FT_Byte*)stream->limit;
p = start;
/* Figure out how long the width table is. */
/* This info is a little-endian short at offset 99. */
p = start + 99;
if ( p + 2 > limit )
{
error = T1_Err_Unknown_File_Format;
goto Exit;
}
width_table_length = LITTLE_ENDIAN_USHORT( p );
p += 18 + width_table_length;
if ( p + 0x12 > limit || LITTLE_ENDIAN_USHORT( p ) < 0x12 )
/* extension table is probably optional */
goto Exit;
/* Kerning offset is 14 bytes from start of extensions table. */
p += 14;
p = start + LITTLE_ENDIAN_UINT( p );
if ( p + 2 > limit )
{
error = T1_Err_Unknown_File_Format;
goto Exit;
}
kern_count = LITTLE_ENDIAN_USHORT( p );
p += 2;
if ( p + 4 * kern_count > limit )
{
error = T1_Err_Unknown_File_Format;
goto Exit;
}
/* Actually, kerning pairs are simply optional! */
if ( kern_count == 0 )
goto Exit;
/* allocate the pairs */
if ( FT_NEW( afm ) || FT_NEW_ARRAY( afm->kern_pairs, kern_count ) )
goto Exit;
/* save in face object */
((T1_Face)t1_face)->afm_data = afm;
t1_face->face_flags |= FT_FACE_FLAG_KERNING;
/* now, read each kern pair */
pair = afm->kern_pairs;
afm->num_pairs = kern_count;
limit = p + 4 * kern_count;
/* PFM kerning data are stored by encoding rather than glyph index, */
/* so find the PostScript charmap of this font and install it */
/* temporarily. If we find no PostScript charmap, then just use */
/* the default and hope it is the right one. */
oldcharmap = t1_face->charmap;
charmap = NULL;
for ( n = 0; n < t1_face->num_charmaps; n++ )
{
charmap = t1_face->charmaps[n];
/* check against PostScript pseudo platform */
if ( charmap->platform_id == 7 )
{
error = FT_Set_Charmap( t1_face, charmap );
if ( error )
goto Exit;
break;
}
}
/* Kerning info is stored as: */
/* */
/* encoding of first glyph (1 byte) */
/* encoding of second glyph (1 byte) */
/* offset (little-endian short) */
for ( ; p < limit ; p+=4 )
{
pair->glyph1 = FT_Get_Char_Index( t1_face, p[0] );
pair->glyph2 = FT_Get_Char_Index( t1_face, p[1] );
pair->kerning.x = (FT_Short)LITTLE_ENDIAN_USHORT(p + 2);
pair->kerning.y = 0;
pair++;
}
if ( oldcharmap != NULL )
error = FT_Set_Charmap( t1_face, oldcharmap );
if ( error )
goto Exit;
/* now, sort the kern pairs according to their glyph indices */
ft_qsort( afm->kern_pairs, kern_count, sizeof ( T1_Kern_Pair ),
compare_kern_pairs );
Exit:
if ( error )
FT_FREE( afm );
return error;
}
/* parse a metrics file -- either AFM or PFM depending on what */
/* it turns out to be */
FT_LOCAL_DEF( FT_Error )
T1_Read_Metrics( FT_Face t1_face,
FT_Stream stream )
{
FT_Error error;
FT_Byte* start;
if ( FT_FRAME_ENTER( stream->size ) )
return error;
start = (FT_Byte*)stream->cursor;
if ( stream->size >= ft_strlen( "StartFontMetrics" ) &&
ft_strncmp( (const char*)start, "StartFontMetrics",
ft_strlen( "StartFontMetrics" ) ) == 0 )
error = T1_Read_AFM( t1_face, stream );
else if ( stream->size > 6 &&
start[0] == 0x00 && start[1] == 0x01 &&
LITTLE_ENDIAN_UINT( start + 2 ) == stream->size )
error = T1_Read_PFM( t1_face, stream );
else
error = T1_Err_Unknown_File_Format;
FT_FRAME_EXIT(); FT_FRAME_EXIT();
return error; return error;

View File

@ -44,12 +44,12 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
T1_Read_AFM( FT_Face face, T1_Read_Metrics( FT_Face face,
FT_Stream stream ); FT_Stream stream );
FT_LOCAL( void ) FT_LOCAL( void )
T1_Done_AFM( FT_Memory memory, T1_Done_Metrics( FT_Memory memory,
T1_AFM* afm ); T1_AFM* afm );
FT_LOCAL( void ) FT_LOCAL( void )
T1_Get_Kerning( T1_AFM* afm, T1_Get_Kerning( T1_AFM* afm,

View File

@ -294,7 +294,7 @@
(FT_Face_AttachFunc) 0, (FT_Face_AttachFunc) 0,
#else #else
(FT_Face_GetKerningFunc) Get_Kerning, (FT_Face_GetKerningFunc) Get_Kerning,
(FT_Face_AttachFunc) T1_Read_AFM, (FT_Face_AttachFunc) T1_Read_Metrics,
#endif #endif
(FT_Face_GetAdvancesFunc) 0 (FT_Face_GetAdvancesFunc) 0
}; };

View File

@ -233,7 +233,7 @@
#ifndef T1_CONFIG_OPTION_NO_AFM #ifndef T1_CONFIG_OPTION_NO_AFM
/* release afm data if present */ /* release afm data if present */
if ( face->afm_data ) if ( face->afm_data )
T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); T1_Done_Metrics( memory, (T1_AFM*)face->afm_data );
#endif #endif
/* release unicode map, if any */ /* release unicode map, if any */