ref: d232f593832f55b6101b6cda1c688a4c5f6add07
parent: 3273a99160a18a327a8a2d31b9e56e69dd9e8c1a
author: Werner Lemberg <[email protected]>
date: Mon Aug 2 01:38:33 EDT 2004
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2004-08-01 Werner Lemberg <[email protected]>
+
+ * docs/CHANGES: Updated.
+
+2004-08-01 George Williams <[email protected]>
+
+ 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 <[email protected]>
* src/pcf/pcfread (pcf_load_font), src/bdf/bdfdrivr.c
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -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
--- a/src/type1/t1afm.c
+++ b/src/type1/t1afm.c
@@ -33,8 +33,8 @@
FT_LOCAL_DEF( void )
- T1_Done_AFM( FT_Memory memory,
- T1_AFM* afm )
+ T1_Done_Metrics( FT_Memory memory,
+ T1_AFM* afm )
{
FT_FREE( afm->kern_pairs );
afm->num_pairs = 0;
@@ -153,11 +153,11 @@
/* 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,
FT_Stream stream )
{
- FT_Error error;
+ FT_Error error = T1_Err_Ok;
FT_Memory memory = stream->memory;
FT_Byte* start;
FT_Byte* limit;
@@ -168,9 +168,6 @@
T1_AFM* afm = 0;
- if ( FT_FRAME_ENTER( stream->size ) )
- return error;
-
start = (FT_Byte*)stream->cursor;
limit = (FT_Byte*)stream->limit;
p = start;
@@ -232,6 +229,173 @@
Exit:
if ( error )
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();
--- a/src/type1/t1afm.h
+++ b/src/type1/t1afm.h
@@ -44,12 +44,12 @@
FT_LOCAL( FT_Error )
- T1_Read_AFM( FT_Face face,
- FT_Stream stream );
+ T1_Read_Metrics( FT_Face face,
+ FT_Stream stream );
FT_LOCAL( void )
- T1_Done_AFM( FT_Memory memory,
- T1_AFM* afm );
+ T1_Done_Metrics( FT_Memory memory,
+ T1_AFM* afm );
FT_LOCAL( void )
T1_Get_Kerning( T1_AFM* afm,
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -294,7 +294,7 @@
(FT_Face_AttachFunc) 0,
#else
(FT_Face_GetKerningFunc) Get_Kerning,
- (FT_Face_AttachFunc) T1_Read_AFM,
+ (FT_Face_AttachFunc) T1_Read_Metrics,
#endif
(FT_Face_GetAdvancesFunc) 0
};
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -233,7 +233,7 @@
#ifndef T1_CONFIG_OPTION_NO_AFM
/* release afm data if present */
if ( face->afm_data )
- T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+ T1_Done_Metrics( memory, (T1_AFM*)face->afm_data );
#endif
/* release unicode map, if any */