From 0489328e974a1f25cd2f8e3dd180468b6bd7be99 Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 6 Feb 2002 11:22:56 +0000 Subject: [PATCH] fixing memory leak in the PCF driver, and managing the "AVERAGE_WIDTH" property in PCF fonts to return correct character pixel (width/height) pairs for embedded bitmaps.. --- ChangeLog | 22 +++++ src/pcf/pcf.h | 5 - src/pcf/pcfdriver.c | 50 +++++----- src/pcf/pcfread.c | 225 ++++++++++++++++++++++---------------------- 4 files changed, 162 insertions(+), 140 deletions(-) diff --git a/ChangeLog b/ChangeLog index f40cab88e..a00d0d86a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2002-02-06 David Turner + + * src/sfnt/ttcmap.c: removing compiler warnings + + * src/pcf/pcfread.c, src/pcf/pcf.h, src/pcf/pcfdriver.c: + removing minor bugs (delaying format checks out of + FT_Access_Frame .. FT_Forget_Frame blocks to avoid leaving the + stream in an incorrect state when encountering an invalid PCF + font) + + reformatting / renaming a few functions for the sake of consistency + + +2002-02-06 Detlef Würkner + + * src/pcf/pcfdriver.c (FT_Done_Face): fixed small memory leak + + * src/pcf/pcfread.c (pcf_load_font): now handles the "AVERAGE_WIDTH" + property to return correct character pixel (width/height) pairs for + embedded bitmaps.. + + 2002-02-04 Keith Packard Adding the function `FT_Get_Next_Char', doing the obvious thing diff --git a/src/pcf/pcf.h b/src/pcf/pcf.h index 3941b6a3f..22d3da4fa 100644 --- a/src/pcf/pcf.h +++ b/src/pcf/pcf.h @@ -159,11 +159,6 @@ FT_BEGIN_HEADER } PCF_FaceRec, *PCF_Face; - /* XXX hack */ - FT_LOCAL FT_Error - PCF_Done_Face( PCF_Face face ); - - /* macros for pcf font format */ #define LSBFirst 0 diff --git a/src/pcf/pcfdriver.c b/src/pcf/pcfdriver.c index d172879d9..864036bbb 100644 --- a/src/pcf/pcfdriver.c +++ b/src/pcf/pcfdriver.c @@ -48,24 +48,32 @@ THE SOFTWARE. #define FT_COMPONENT trace_pcfdriver - FT_LOCAL_DEF FT_Error - PCF_Done_Face( PCF_Face face ) + static FT_Error + PCF_Face_Done( PCF_Face face ) { FT_Memory memory = FT_FACE_MEMORY( face ); - PCF_Property tmp = face->properties; - int i; FREE( face->encodings ); FREE( face->metrics ); - for ( i = 0; i < face->nprops; i++ ) + /* free properties */ { - FREE( tmp->name ); - if ( tmp->isString ) - FREE( tmp->value ); + PCF_Property prop = face->properties; + FT_Int i; + + for ( i = 0; i < face->nprops; i++ ) + { + prop = &face->properties[i]; + + FREE( prop->name ); + if ( prop->isString ) + FREE( prop->value ); + } + + FREE( face->properties ); } - FREE( face->properties ); + FREE( face->toc.tables ); FREE( face->root.family_name ); FREE( face->root.available_sizes ); @@ -79,7 +87,7 @@ THE SOFTWARE. static FT_Error - PCF_Init_Face( FT_Stream stream, + PCF_Face_Init( FT_Stream stream, PCF_Face face, FT_Int face_index, FT_Int num_params, @@ -100,7 +108,7 @@ THE SOFTWARE. Fail: FT_TRACE2(( "[not a valid PCF file]\n" )); - PCF_Done_Face( face ); + PCF_Face_Done( face ); return PCF_Err_Unknown_File_Format; /* error */ } @@ -138,19 +146,19 @@ THE SOFTWARE. static FT_Error - PCF_Load_Glyph( FT_GlyphSlot slot, + PCF_Glyph_Load( FT_GlyphSlot slot, FT_Size size, FT_UInt glyph_index, FT_Int load_flags ) { PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + FT_Stream stream = face->root.stream; FT_Error error = PCF_Err_Ok; FT_Memory memory = FT_FACE(face)->memory; FT_Bitmap* bitmap = &slot->bitmap; PCF_Metric metric; int bytes; - FT_Stream stream = face->root.stream; FT_UNUSED( load_flags ); @@ -249,7 +257,7 @@ THE SOFTWARE. static FT_UInt - PCF_Get_Char_Index( FT_CharMap charmap, + PCF_Char_Get_Index( FT_CharMap charmap, FT_Long char_code ) { PCF_Face face = (PCF_Face)charmap->face; @@ -277,7 +285,7 @@ THE SOFTWARE. static FT_Long - PCF_Get_Next_Char( FT_CharMap charmap, + PCF_Char_Get_Next( FT_CharMap charmap, FT_Long char_code ) { PCF_Face face = (PCF_Face)charmap->face; @@ -285,7 +293,7 @@ THE SOFTWARE. int low, high, mid; - FT_TRACE4(( "get_char_index %ld\n", char_code )); + FT_TRACE4(( "get_next_char %ld\n", char_code )); char_code++; low = 0; @@ -338,8 +346,8 @@ THE SOFTWARE. sizeof( FT_SizeRec ), sizeof( FT_GlyphSlotRec ), - (FTDriver_initFace) PCF_Init_Face, - (FTDriver_doneFace) PCF_Done_Face, + (FTDriver_initFace) PCF_Face_Init, + (FTDriver_doneFace) PCF_Face_Done, (FTDriver_initSize) 0, (FTDriver_doneSize) 0, (FTDriver_initGlyphSlot)0, @@ -348,14 +356,14 @@ THE SOFTWARE. (FTDriver_setCharSizes) PCF_Set_Pixel_Size, (FTDriver_setPixelSizes)PCF_Set_Pixel_Size, - (FTDriver_loadGlyph) PCF_Load_Glyph, - (FTDriver_getCharIndex) PCF_Get_Char_Index, + (FTDriver_loadGlyph) PCF_Glyph_Load, + (FTDriver_getCharIndex) PCF_Char_Get_Index, (FTDriver_getKerning) 0, (FTDriver_attachFile) 0, (FTDriver_getAdvances) 0, - (FTDriver_getNextChar) PCF_Get_Next_Char + (FTDriver_getNextChar) PCF_Char_Get_Next, }; diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c index 07acee32e..ffb28e980 100644 --- a/src/pcf/pcfread.c +++ b/src/pcf/pcfread.c @@ -94,8 +94,8 @@ THE SOFTWARE. PCF_Toc toc = &face->toc; PCF_Table tables; - FT_Memory memory = FT_FACE(face)->memory; - unsigned int n; + FT_Memory memory = FT_FACE(face)->memory; + FT_UInt n; if ( FILE_Seek ( 0 ) || @@ -119,8 +119,8 @@ THE SOFTWARE. #if defined( FT_DEBUG_LEVEL_TRACE ) { - unsigned int i, j; - const char *name = "?"; + FT_UInt i, j; + const char* name = "?"; FT_TRACE4(( "Tables count: %ld\n", face->toc.count )); @@ -128,8 +128,9 @@ THE SOFTWARE. for ( i = 0; i < toc->count; i++ ) { for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) - if ( tables[i].type == (unsigned int)( 1 << j ) ) + if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; + FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX " "size=0x%06lX (%8ld) offset=0x%04lX\n", i, name, @@ -199,46 +200,6 @@ THE SOFTWARE. }; - static FT_Error - pcf_parse_metric( FT_Stream stream, - const FT_Frame_Field* header, - PCF_Metric metric ) - { - FT_Error error = PCF_Err_Ok; - - - if ( READ_Fields( header, metric ) ) - return error; - - return PCF_Err_Ok; - } - - - static FT_Error - pcf_parse_compressed_metric( FT_Stream stream, - PCF_Metric metric ) - { - PCF_Compressed_MetricRec compr_metric; - FT_Error error = PCF_Err_Ok; - - - if ( READ_Fields( pcf_compressed_metric_header, &compr_metric ) ) - return error; - - metric->leftSideBearing = - (FT_Short)( compr_metric.leftSideBearing - 0x80 ); - metric->rightSideBearing = - (FT_Short)( compr_metric.rightSideBearing - 0x80 ); - metric->characterWidth = - (FT_Short)( compr_metric.characterWidth - 0x80 ); - metric->ascent = - (FT_Short)( compr_metric.ascent - 0x80 ); - metric->descent = - (FT_Short)( compr_metric.descent - 0x80 ); - metric->attributes = 0; - - return PCF_Err_Ok; - } static FT_Error @@ -246,33 +207,53 @@ THE SOFTWARE. FT_ULong format, PCF_Metric metric ) { - FT_Error error = PCF_Err_Ok; + FT_Error error = PCF_Err_Ok; if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { - if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - error = pcf_parse_metric( stream, pcf_metric_msb_header, metric ); - else - error = pcf_parse_metric( stream, pcf_metric_header, metric ); + const FT_Frame_Field* fields; + + /* parsing normal metrics */ + fields = PCF_BYTE_ORDER( format ) == MSBFirst + ? pcf_metric_msb_header + : pcf_metric_header; + + /* the following sets 'error' but doesn't return in case of failure */ + (void) READ_Fields( fields, metric ); } else - error = pcf_parse_compressed_metric( stream, metric ); + { + PCF_Compressed_MetricRec compr; + + /* parsing compressed metrics */ + if ( READ_Fields( pcf_compressed_metric_header, &compr ) ) + goto Exit; + + metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 ); + metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 ); + metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 ); + metric->ascent = (FT_Short)( compr.ascent - 0x80 ); + metric->descent = (FT_Short)( compr.descent - 0x80 ); + metric->attributes = 0; + } + + Exit: return error; } static FT_Error - pcfSeekToType( FT_Stream stream, - PCF_Table tables, - int ntables, - FT_ULong type, - FT_ULong* formatp, - FT_ULong* sizep ) + pcf_seek_to_table_type( FT_Stream stream, + PCF_Table tables, + FT_Int ntables, + FT_ULong type, + FT_ULong *aformat, + FT_ULong *asize ) { FT_Error error; - int i; + FT_Int i; for ( i = 0; i < ntables; i++ ) @@ -280,10 +261,13 @@ THE SOFTWARE. { if ( stream->pos > tables[i].offset ) return PCF_Err_Invalid_Stream_Skip; + if ( FILE_Skip( tables[i].offset - stream->pos ) ) return PCF_Err_Invalid_Stream_Skip; - *sizep = tables[i].size; /* unused - to be removed */ - *formatp = tables[i].format; + + *asize = tables[i].size; /* unused - to be removed */ + *aformat = tables[i].format; + return PCF_Err_Ok; } @@ -292,11 +276,11 @@ THE SOFTWARE. static FT_Bool - pcfHasType( PCF_Table tables, - int ntables, - FT_ULong type ) + pcf_has_table_type( PCF_Table tables, + FT_Int ntables, + FT_ULong type ) { - int i; + FT_Int i; for ( i = 0; i < ntables; i++ ) @@ -336,8 +320,8 @@ THE SOFTWARE. static PCF_Property - find_property( PCF_Face face, - const FT_String* prop ) + pcf_find_property( PCF_Face face, + const FT_String* prop ) { PCF_Property properties = face->properties; FT_Bool found = 0; @@ -363,7 +347,7 @@ THE SOFTWARE. { PCF_ParseProperty props = 0; PCF_Property properties = 0; - int nprops, i; + FT_Int nprops, i; FT_ULong format, size; FT_Error error; FT_Memory memory = FT_FACE(face)->memory; @@ -371,12 +355,12 @@ THE SOFTWARE. FT_String* strings = 0; - error = pcfSeekToType( stream, - face->toc.tables, - face->toc.count, - PCF_PROPERTIES, - &format, - &size ); + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_PROPERTIES, + &format, + &size ); if ( error ) goto Bail; @@ -496,7 +480,7 @@ THE SOFTWARE. int nmetrics = -1; - error = pcfSeekToType( stream, + error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_METRICS, @@ -573,35 +557,36 @@ THE SOFTWARE. char* bitmaps; - error = pcfSeekToType( stream, - face->toc.tables, - face->toc.count, - PCF_BITMAPS, - &format, - &size ); + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_BITMAPS, + &format, + &size ); if ( error ) return error; error = FT_Access_Frame( stream, 8 ); if ( error ) return error; - format = GET_ULongLE(); - if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) - return PCF_Err_Invalid_File_Format; + format = GET_ULongLE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) nbitmaps = GET_ULong(); else nbitmaps = GET_ULongLE(); + FT_Forget_Frame( stream ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return PCF_Err_Invalid_File_Format; + if ( nbitmaps != face->nmetrics ) return PCF_Err_Invalid_File_Format; if ( ALLOC( offsets, nbitmaps * sizeof ( FT_ULong ) ) ) return error; - if ( error ) - goto Bail; for ( i = 0; i < nbitmaps; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) @@ -614,8 +599,6 @@ THE SOFTWARE. if ( error ) goto Bail; - if ( error ) - goto Bail; for ( i = 0; i < GLYPHPADOPTIONS; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) @@ -664,7 +647,7 @@ THE SOFTWARE. PCF_Encoding tmpEncoding, encoding = 0; - error = pcfSeekToType( stream, + error = pcf_seek_to_table_type( stream, face->toc.tables, face->toc.count, PCF_BDF_ENCODINGS, @@ -676,9 +659,8 @@ THE SOFTWARE. error = FT_Access_Frame( stream, 14 ); if ( error ) return error; + format = GET_ULongLE(); - if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) - return PCF_Err_Invalid_File_Format; if ( PCF_BYTE_ORDER( format ) == MSBFirst ) { @@ -699,6 +681,9 @@ THE SOFTWARE. FT_Forget_Frame( stream ); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return PCF_Err_Invalid_File_Format; + FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", firstCol, lastCol, firstRow, lastRow )); @@ -810,16 +795,17 @@ THE SOFTWARE. PCF_Accel accel = &face->accel; - error = pcfSeekToType( stream, - face->toc.tables, - face->toc.count, - type, - &format, - &size ); + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + type, + &format, + &size ); if ( error ) goto Bail; error = READ_ULongLE( format ); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) goto Bail; @@ -838,6 +824,7 @@ THE SOFTWARE. error = pcf_get_metric( stream, format, &(accel->minbounds) ); if ( error ) goto Bail; + error = pcf_get_metric( stream, format, &(accel->maxbounds) ); if ( error ) goto Bail; @@ -847,6 +834,7 @@ THE SOFTWARE. error = pcf_get_metric( stream, format, &(accel->ink_minbounds) ); if ( error ) goto Bail; + error = pcf_get_metric( stream, format, &(accel->ink_maxbounds) ); if ( error ) goto Bail; @@ -881,7 +869,7 @@ THE SOFTWARE. return error;; /* Use the old accelerators if no BDF accelerators are in the file. */ - hasBDFAccelerators = pcfHasType( face->toc.tables, + hasBDFAccelerators = pcf_has_table_type( face->toc.tables, face->toc.count, PCF_BDF_ACCELERATORS ); if ( !hasBDFAccelerators ) @@ -933,14 +921,14 @@ THE SOFTWARE. root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; root->style_flags = 0; - prop = find_property( face, "SLANT" ); + prop = pcf_find_property( face, "SLANT" ); if ( prop != NULL ) if ( prop->isString ) if ( ( *(prop->value.atom) == 'O' ) || ( *(prop->value.atom) == 'I' ) ) root->style_flags |= FT_STYLE_FLAG_ITALIC; - prop = find_property( face, "WEIGHT_NAME" ); + prop = pcf_find_property( face, "WEIGHT_NAME" ); if ( prop != NULL ) if ( prop->isString ) if ( *(prop->value.atom) == 'B' ) @@ -957,7 +945,7 @@ THE SOFTWARE. else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) root->style_name = (char *)"Italic"; - prop = find_property( face, "FAMILY_NAME" ); + prop = pcf_find_property( face, "FAMILY_NAME" ); if ( prop != NULL ) { if ( prop->isString ) @@ -979,33 +967,43 @@ THE SOFTWARE. if ( ALLOC_ARRAY( root->available_sizes, 1, FT_Bitmap_Size ) ) goto Bail; - prop = find_property( face, "PIXEL_SIZE" ); + prop = pcf_find_property( face, "PIXEL_SIZE" ); if ( prop != NULL ) { + root->available_sizes->height = root->available_sizes->width = (FT_Short)( prop->value.integer ); - root->available_sizes->height = (FT_Short)( prop->value.integer ); + + prop = pcf_find_property( face, "AVERAGE_WIDTH" ); + if ( prop != NULL ) + root->available_sizes->width = (FT_Short)( prop->value.integer / 10 ); size_set = 1; } else { - prop = find_property( face, "POINT_SIZE" ); + prop = pcf_find_property( face, "POINT_SIZE" ); if ( prop != NULL ) { - PCF_Property xres = 0, yres = 0; + PCF_Property xres, yres, avgw; - xres = find_property( face, "RESOLUTION_X" ); - yres = find_property( face, "RESOLUTION_Y" ); - - if ( ( xres != NULL ) && ( yres != NULL ) ) + xres = pcf_find_property( face, "RESOLUTION_X" ); + yres = pcf_find_property( face, "RESOLUTION_Y" ); + avgw = pcf_find_property( face, "AVERAGE_WIDTH" ); + + if ( ( yres != NULL ) && ( ( xres != NULL ) || ( avgw == NULL ) ) ) { - root->available_sizes->width = - (FT_Short)( prop->value.integer * - xres->value.integer / 720 ); root->available_sizes->height = (FT_Short)( prop->value.integer * yres->value.integer / 720 ); + + if ( avgw != NULL ) + root->available_sizes->width = + (FT_Short)( avgw->value.integer / 10 ); + else + root->available_sizes->width = + (FT_Short)( prop->value.integer * + xres->value.integer / 720 ); size_set = 1; } @@ -1033,8 +1031,8 @@ THE SOFTWARE. PCF_Property charset_registry = 0, charset_encoding = 0; - charset_registry = find_property( face, "CHARSET_REGISTRY" ); - charset_encoding = find_property( face, "CHARSET_ENCODING" ); + charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" ); + charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" ); if ( ( charset_registry != NULL ) && ( charset_encoding != NULL ) ) @@ -1072,7 +1070,6 @@ THE SOFTWARE. return PCF_Err_Ok; Bail: - PCF_Done_Face( face ); return PCF_Err_Invalid_File_Format; }