diff options
Diffstat (limited to 'modules/freetype2/src/pcf/pcfread.c')
-rw-r--r-- | modules/freetype2/src/pcf/pcfread.c | 450 |
1 files changed, 326 insertions, 124 deletions
diff --git a/modules/freetype2/src/pcf/pcfread.c b/modules/freetype2/src/pcf/pcfread.c index 95ee57018..537da0dc7 100644 --- a/modules/freetype2/src/pcf/pcfread.c +++ b/modules/freetype2/src/pcf/pcfread.c @@ -50,8 +50,15 @@ THE SOFTWARE. #ifdef FT_DEBUG_LEVEL_TRACE static const char* const tableNames[] = { - "prop", "accl", "mtrcs", "bmps", "imtrcs", - "enc", "swidth", "names", "accel" + "properties", + "accelerators", + "metrics", + "bitmaps", + "ink metrics", + "encodings", + "swidths", + "glyph names", + "BDF accelerators" }; #endif @@ -109,22 +116,20 @@ THE SOFTWARE. if ( stream->size < 16 ) return FT_THROW( Invalid_File_Format ); - /* We need 16 bytes per TOC entry. Additionally, as a */ - /* heuristic protection against gzip bombs (i.e., very */ - /* small input files that expand to insanely large */ - /* files), we limit the number of TOC entries to 1024. */ - if ( toc->count > stream->size >> 4 || - toc->count > 1024 ) + /* we need 16 bytes per TOC entry, */ + /* and there can be most 9 tables */ + if ( toc->count > ( stream->size >> 4 ) || + toc->count > 9 ) { FT_TRACE0(( "pcf_read_TOC: adjusting number of tables" " (from %d to %d)\n", toc->count, - FT_MIN( stream->size >> 4, 1024 ) )); - toc->count = FT_MIN( stream->size >> 4, 1024 ); + FT_MIN( stream->size >> 4, 9 ) )); + toc->count = FT_MIN( stream->size >> 4, 9 ); } if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) - return FT_THROW( Out_Of_Memory ); + return error; tables = face->toc.tables; for ( n = 0; n < toc->count; n++ ) @@ -237,8 +242,8 @@ THE SOFTWARE. if ( tables[i].type == (FT_UInt)( 1 << j ) ) name = tableNames[j]; - FT_TRACE4(( " %d: type=%s, format=0x%X, " - "size=%ld (0x%lX), offset=%ld (0x%lX)\n", + FT_TRACE4(( " %d: type=%s, format=0x%X," + " size=%ld (0x%lX), offset=%ld (0x%lX)\n", i, name, tables[i].format, tables[i].size, tables[i].size, @@ -348,6 +353,17 @@ THE SOFTWARE. metric->attributes = 0; } + FT_TRACE5(( " width=%d," + " lsb=%d, rsb=%d," + " ascent=%d, descent=%d," + " attributes=%d\n", + metric->characterWidth, + metric->leftSideBearing, + metric->rightSideBearing, + metric->ascent, + metric->descent, + metric->attributes )); + Exit: return error; } @@ -466,7 +482,7 @@ THE SOFTWARE. { PCF_ParseProperty props = NULL; PCF_Property properties = NULL; - FT_ULong nprops, i; + FT_ULong nprops, orig_nprops, i; FT_ULong format, size; FT_Error error; FT_Memory memory = FT_FACE( face )->memory; @@ -486,32 +502,43 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; - FT_TRACE4(( "pcf_get_properties:\n" )); - - FT_TRACE4(( " format = %ld\n", format )); + FT_TRACE4(( "pcf_get_properties:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) goto Bail; if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nprops ); + (void)FT_READ_ULONG( orig_nprops ); else - (void)FT_READ_ULONG_LE( nprops ); + (void)FT_READ_ULONG_LE( orig_nprops ); if ( error ) goto Bail; - FT_TRACE4(( " nprop = %d (truncate %d props)\n", - (int)nprops, nprops - (FT_ULong)(int)nprops )); - - nprops = (FT_ULong)(int)nprops; + FT_TRACE4(( " number of properties: %ld\n", orig_nprops )); /* rough estimate */ - if ( nprops > size / PCF_PROPERTY_SIZE ) + if ( orig_nprops > size / PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* as a heuristic limit to avoid excessive allocation in */ + /* gzip bombs (i.e., very small, invalid input data that */ + /* pretends to expand to an insanely large file) we only */ + /* load the first 256 properties */ + if ( orig_nprops > 256 ) + { + FT_TRACE0(( "pcf_get_properties:" + " only loading first 256 properties\n" )); + nprops = 256; + } + else + nprops = orig_nprops; + face->nprops = (int)nprops; if ( FT_NEW_ARRAY( props, nprops ) ) @@ -531,14 +558,23 @@ THE SOFTWARE. } } + /* this skip will only work if we really have an extremely large */ + /* number of properties; it will fail for fake data, avoiding an */ + /* unnecessarily large allocation later on */ + if ( FT_STREAM_SKIP( ( orig_nprops - nprops ) * PCF_PROPERTY_SIZE ) ) + { + error = FT_THROW( Invalid_Stream_Skip ); + goto Bail; + } + /* pad the property array */ /* */ /* clever here - nprops is the same as the number of odd-units read, */ /* as only isStringProp are odd length (Keith Packard) */ /* */ - if ( nprops & 3 ) + if ( orig_nprops & 3 ) { - i = 4 - ( nprops & 3 ); + i = 4 - ( orig_nprops & 3 ); if ( FT_STREAM_SKIP( i ) ) { error = FT_THROW( Invalid_Stream_Skip ); @@ -553,15 +589,24 @@ THE SOFTWARE. if ( error ) goto Bail; - FT_TRACE4(( " string_size = %ld\n", string_size )); + FT_TRACE4(( " string size: %ld\n", string_size )); /* rough estimate */ - if ( string_size > size - nprops * PCF_PROPERTY_SIZE ) + if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE ) { error = FT_THROW( Invalid_Table ); goto Bail; } + /* the strings in the `strings' array are PostScript strings, */ + /* which can have a maximum length of 65536 characters each */ + if ( string_size > 16777472 ) /* 256 * (65536 + 1) */ + { + FT_TRACE0(( "pcf_get_properties:" + " loading only 16777472 bytes of strings array\n" )); + string_size = 16777472; + } + /* allocate one more byte so that we have a final null byte */ if ( FT_NEW_ARRAY( strings, string_size + 1 ) ) goto Bail; @@ -575,6 +620,7 @@ THE SOFTWARE. face->properties = properties; + FT_TRACE4(( "\n" )); for ( i = 0; i < nprops; i++ ) { FT_Long name_offset = props[i].name; @@ -637,7 +683,7 @@ THE SOFTWARE. FT_Memory memory = FT_FACE( face )->memory; FT_ULong format, size; PCF_Metric metrics = NULL; - FT_ULong nmetrics, i; + FT_ULong nmetrics, orig_nmetrics, i; error = pcf_seek_to_table_type( stream, @@ -652,6 +698,13 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_metrics:\n" + " format: 0x%lX (%s, %s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ? + "compressed" : "uncompressed" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) return FT_THROW( Invalid_File_Format ); @@ -659,61 +712,70 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_ULONG( nmetrics ); + (void)FT_READ_ULONG( orig_nmetrics ); else - (void)FT_READ_ULONG_LE( nmetrics ); + (void)FT_READ_ULONG_LE( orig_nmetrics ); } else { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - (void)FT_READ_USHORT( nmetrics ); + (void)FT_READ_USHORT( orig_nmetrics ); else - (void)FT_READ_USHORT_LE( nmetrics ); + (void)FT_READ_USHORT_LE( orig_nmetrics ); } if ( error ) return FT_THROW( Invalid_File_Format ); - face->nmetrics = nmetrics; - - if ( !nmetrics ) - return FT_THROW( Invalid_Table ); - - FT_TRACE4(( "pcf_get_metrics:\n" )); - - FT_TRACE4(( " number of metrics: %d\n", nmetrics )); + FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics )); /* rough estimate */ if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) { - if ( nmetrics > size / PCF_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } else { - if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) + if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE ) return FT_THROW( Invalid_Table ); } + if ( !orig_nmetrics ) + return FT_THROW( Invalid_Table ); + + /* PCF is a format from ancient times; Unicode was in its */ + /* infancy, and widely used two-byte character sets for CJK */ + /* scripts (Big 5, GB 2312, JIS X 0208, etc.) did have at most */ + /* 15000 characters. Even the more exotic CNS 11643 and CCCII */ + /* standards, which were essentially three-byte character sets, */ + /* provided less then 65536 assigned characters. */ + /* */ + /* While technically possible to have a larger number of glyphs */ + /* in PCF files, we thus limit the number to 65536. */ + if ( orig_nmetrics > 65536 ) + { + FT_TRACE0(( "pcf_get_metrics:" + " only loading first 65536 metrics\n" )); + nmetrics = 65536; + } + else + nmetrics = orig_nmetrics; + + face->nmetrics = nmetrics; + if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) - return FT_THROW( Out_Of_Memory ); + return error; metrics = face->metrics; + + FT_TRACE4(( "\n" )); for ( i = 0; i < nmetrics; i++, metrics++ ) { + FT_TRACE5(( " idx %ld:", i )); error = pcf_get_metric( stream, format, metrics ); metrics->bits = 0; - FT_TRACE5(( " idx %d: width=%d, " - "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", - i, - metrics->characterWidth, - metrics->leftSideBearing, - metrics->rightSideBearing, - metrics->ascent, - metrics->descent, - metrics->attributes )); - if ( error ) break; @@ -721,7 +783,7 @@ THE SOFTWARE. /* compute a glyph's bitmap dimensions, thus setting them to zero in */ /* case of an error disables this particular glyph only */ if ( metrics->rightSideBearing < metrics->leftSideBearing || - metrics->ascent + metrics->descent < 0 ) + metrics->ascent < -metrics->descent ) { metrics->characterWidth = 0; metrics->leftSideBearing = 0; @@ -751,7 +813,7 @@ THE SOFTWARE. FT_Long* offsets = NULL; FT_Long bitmapSizes[GLYPHPADOPTIONS]; FT_ULong format, size; - FT_ULong nbitmaps, i, sizebitmaps = 0; + FT_ULong nbitmaps, orig_nbitmaps, i, sizebitmaps = 0; error = pcf_seek_to_table_type( stream, @@ -769,18 +831,42 @@ THE SOFTWARE. format = FT_GET_ULONG_LE(); if ( PCF_BYTE_ORDER( format ) == MSBFirst ) - nbitmaps = FT_GET_ULONG(); + orig_nbitmaps = FT_GET_ULONG(); else - nbitmaps = FT_GET_ULONG_LE(); + orig_nbitmaps = FT_GET_ULONG_LE(); FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_bitmaps:\n" + " format: 0x%lX\n" + " (%s, %s,\n" + " padding=%d bit%s, scanning=%d bit%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst + ? "most significant byte first" + : "least significant byte first", + PCF_BIT_ORDER( format ) == MSBFirst + ? "most significant bit first" + : "least significant bit first", + 8 << PCF_GLYPH_PAD_INDEX( format ), + ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s", + 8 << PCF_SCAN_UNIT_INDEX( format ), + ( 8 << PCF_SCAN_UNIT_INDEX( format ) ) == 1 ? "" : "s" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - FT_TRACE4(( "pcf_get_bitmaps:\n" )); + FT_TRACE4(( " number of bitmaps: %ld\n", orig_nbitmaps )); - FT_TRACE4(( " number of bitmaps: %d\n", nbitmaps )); + /* see comment in `pcf_get_metrics' */ + if ( orig_nbitmaps > 65536 ) + { + FT_TRACE0(( "pcf_get_bitmaps:" + " only loading first 65536 bitmaps\n" )); + nbitmaps = 65536; + } + else + nbitmaps = orig_nbitmaps; if ( nbitmaps != face->nmetrics ) return FT_THROW( Invalid_File_Format ); @@ -788,6 +874,7 @@ THE SOFTWARE. if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) return error; + FT_TRACE5(( "\n" )); for ( i = 0; i < nbitmaps; i++ ) { if ( PCF_BYTE_ORDER( format ) == MSBFirst ) @@ -795,7 +882,7 @@ THE SOFTWARE. else (void)FT_READ_LONG_LE( offsets[i] ); - FT_TRACE5(( " bitmap %d: offset %ld (0x%lX)\n", + FT_TRACE5(( " bitmap %ld: offset %ld (0x%lX)\n", i, offsets[i], offsets[i] )); } if ( error ) @@ -812,17 +899,19 @@ THE SOFTWARE. sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; - FT_TRACE4(( " padding %d implies a size of %ld\n", - i, bitmapSizes[i] )); + FT_TRACE4(( " %ld-bit padding implies a size of %ld\n", + 8 << i, bitmapSizes[i] )); } - FT_TRACE4(( " %d bitmaps, padding index %ld\n", + FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n", nbitmaps, - PCF_GLYPH_PAD_INDEX( format ) )); - FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); + 8 << PCF_GLYPH_PAD_INDEX( format ) )); + FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps )); FT_UNUSED( sizebitmaps ); /* only used for debugging */ + /* right now, we only check the bitmap offsets; */ + /* actual bitmaps are only loaded on demand */ for ( i = 0; i < nbitmaps; i++ ) { /* rough estimate */ @@ -830,7 +919,7 @@ THE SOFTWARE. ( (FT_ULong)offsets[i] > size ) ) { FT_TRACE0(( "pcf_get_bitmaps:" - " invalid offset to bitmap data of glyph %d\n", i )); + " invalid offset to bitmap data of glyph %ld\n", i )); } else face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i]; @@ -894,10 +983,20 @@ THE SOFTWARE. FT_Stream_ExitFrame( stream ); + FT_TRACE4(( "pcf_get_encodings:\n" + " format: 0x%lX (%s)\n", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) return FT_THROW( Invalid_File_Format ); - /* sanity checks */ + FT_TRACE4(( " firstCol 0x%X, lastCol 0x%X\n" + " firstRow 0x%X, lastRow 0x%X\n", + firstCol, lastCol, + firstRow, lastRow )); + + /* sanity checks; we limit numbers of rows and columns to 256 */ if ( firstCol < 0 || firstCol > lastCol || lastCol > 0xFF || @@ -906,21 +1005,18 @@ THE SOFTWARE. lastRow > 0xFF ) return FT_THROW( Invalid_Table ); - FT_TRACE4(( "pdf_get_encodings:\n" )); - - FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", - firstCol, lastCol, firstRow, lastRow )); - nencoding = (FT_ULong)( lastCol - firstCol + 1 ) * (FT_ULong)( lastRow - firstRow + 1 ); if ( FT_NEW_ARRAY( encoding, nencoding ) ) - return FT_THROW( Out_Of_Memory ); + return error; error = FT_Stream_EnterFrame( stream, 2 * nencoding ); if ( error ) goto Bail; + FT_TRACE5(( "\n" )); + k = 0; for ( i = firstRow; i <= lastRow; i++ ) { @@ -1029,6 +1125,15 @@ THE SOFTWARE. if ( FT_READ_ULONG_LE( format ) ) goto Bail; + FT_TRACE4(( "pcf_get_accel%s:\n" + " format: 0x%lX (%s, %s)\n", + type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)" + : "", + format, + PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB", + PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ? + "accelerated" : "not accelerated" )); + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) goto Bail; @@ -1044,12 +1149,43 @@ THE SOFTWARE. goto Bail; } + FT_TRACE5(( " noOverlap=%s, constantMetrics=%s," + " terminalFont=%s, constantWidth=%s\n" + " inkInside=%s, inkMetrics=%s, drawDirection=%s\n" + " fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n", + accel->noOverlap ? "yes" : "no", + accel->constantMetrics ? "yes" : "no", + accel->terminalFont ? "yes" : "no", + accel->constantWidth ? "yes" : "no", + accel->inkInside ? "yes" : "no", + accel->inkMetrics ? "yes" : "no", + accel->drawDirection ? "RTL" : "LTR", + accel->fontAscent, + accel->fontDescent, + accel->maxOverlap )); + + /* sanity checks */ + if ( FT_ABS( accel->fontAscent ) > 0x7FFF ) + { + accel->fontAscent = accel->fontAscent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "pfc_get_accel: clamping font ascent to value %d\n", + accel->fontAscent )); + } + if ( FT_ABS( accel->fontDescent ) > 0x7FFF ) + { + accel->fontDescent = accel->fontDescent < 0 ? -0x7FFF : 0x7FFF; + FT_TRACE0(( "pfc_get_accel: clamping font descent to value %d\n", + accel->fontDescent )); + } + + FT_TRACE5(( " minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->maxbounds) ); @@ -1058,12 +1194,14 @@ THE SOFTWARE. if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) { + FT_TRACE5(( " ink minbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_minbounds) ); if ( error ) goto Bail; + FT_TRACE5(( " ink maxbounds:" )); error = pcf_get_metric( stream, format & ( ~PCF_FORMAT_MASK ), &(accel->ink_maxbounds) ); @@ -1072,7 +1210,7 @@ THE SOFTWARE. } else { - accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ + accel->ink_minbounds = accel->minbounds; accel->ink_maxbounds = accel->maxbounds; } @@ -1271,57 +1409,75 @@ THE SOFTWARE. prop = pcf_find_property( face, "FAMILY_NAME" ); if ( prop && prop->isString ) { - /* Prepend the foundry name plus a space to the family name. */ - /* There are many fonts just called `Fixed' which look completely */ - /* different, and which have nothing to do with each other. When */ - /* selecting `Fixed' in KDE or Gnome one gets results that appear */ - /* rather random, the style changes often if one changes the size */ - /* and one cannot select some fonts at all. */ - /* */ - /* We also check whether we have `wide' characters; all put */ - /* together, we get family names like `Sony Fixed' or `Misc Fixed */ - /* Wide'. */ - PCF_Property foundry_prop, point_size_prop, average_width_prop; - - int l = ft_strlen( prop->value.atom ) + 1; - int wide = 0; - - - foundry_prop = pcf_find_property( face, "FOUNDRY" ); - point_size_prop = pcf_find_property( face, "POINT_SIZE" ); - average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); - - if ( point_size_prop && average_width_prop ) + +#ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES + + PCF_Driver driver = (PCF_Driver)FT_FACE_DRIVER( face ); + + + if ( !driver->no_long_family_names ) { - if ( average_width_prop->value.l >= point_size_prop->value.l ) + /* Prepend the foundry name plus a space to the family name. */ + /* There are many fonts just called `Fixed' which look */ + /* completely different, and which have nothing to do with each */ + /* other. When selecting `Fixed' in KDE or Gnome one gets */ + /* results that appear rather random, the style changes often if */ + /* one changes the size and one cannot select some fonts at all. */ + /* */ + /* We also check whether we have `wide' characters; all put */ + /* together, we get family names like `Sony Fixed' or `Misc */ + /* Fixed Wide'. */ + + PCF_Property foundry_prop, point_size_prop, average_width_prop; + + int l = ft_strlen( prop->value.atom ) + 1; + int wide = 0; + + + foundry_prop = pcf_find_property( face, "FOUNDRY" ); + point_size_prop = pcf_find_property( face, "POINT_SIZE" ); + average_width_prop = pcf_find_property( face, "AVERAGE_WIDTH" ); + + if ( point_size_prop && average_width_prop ) { - /* This font is at least square shaped or even wider */ - wide = 1; - l += ft_strlen( " Wide" ); + if ( average_width_prop->value.l >= point_size_prop->value.l ) + { + /* This font is at least square shaped or even wider */ + wide = 1; + l += ft_strlen( " Wide" ); + } } - } - if ( foundry_prop && foundry_prop->isString ) - { - l += ft_strlen( foundry_prop->value.atom ) + 1; + if ( foundry_prop && foundry_prop->isString ) + { + l += ft_strlen( foundry_prop->value.atom ) + 1; - if ( FT_NEW_ARRAY( root->family_name, l ) ) - goto Exit; + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, foundry_prop->value.atom ); + ft_strcat( root->family_name, " " ); + ft_strcat( root->family_name, prop->value.atom ); + } + else + { + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + + ft_strcpy( root->family_name, prop->value.atom ); + } - ft_strcpy( root->family_name, foundry_prop->value.atom ); - ft_strcat( root->family_name, " " ); - ft_strcat( root->family_name, prop->value.atom ); + if ( wide ) + ft_strcat( root->family_name, " Wide" ); } else + +#endif /* PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + { - if ( FT_NEW_ARRAY( root->family_name, l ) ) + if ( FT_STRDUP( root->family_name, prop->value.atom ) ) goto Exit; - - ft_strcpy( root->family_name, prop->value.atom ); } - - if ( wide ) - ft_strcat( root->family_name, " Wide" ); } else root->family_name = NULL; @@ -1356,8 +1512,16 @@ THE SOFTWARE. if ( face->accel.fontAscent + face->accel.fontDescent < 0 ) FT_TRACE0(( "pcf_load_font: negative height\n" )); #endif - bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent + - face->accel.fontDescent ) ); + if ( FT_ABS( face->accel.fontAscent + + face->accel.fontDescent ) > 0x7FFF ) + { + bsize->height = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping height to value %d\n", + bsize->height )); + } + else + bsize->height = FT_ABS( (FT_Short)( face->accel.fontAscent + + face->accel.fontDescent ) ); prop = pcf_find_property( face, "AVERAGE_WIDTH" ); if ( prop ) @@ -1366,10 +1530,20 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative average width\n" )); #endif - bsize->width = FT_ABS( (FT_Short)( ( prop->value.l ) + 5 ) / 10 ); + if ( ( FT_ABS( prop->value.l ) > 0x7FFFL * 10 - 5 ) ) + { + bsize->width = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping average width to value %d\n", + bsize->width )); + } + else + bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) ); } else + { + /* this is a heuristical value */ bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 ); + } prop = pcf_find_property( face, "POINT_SIZE" ); if ( prop ) @@ -1379,9 +1553,16 @@ THE SOFTWARE. FT_TRACE0(( "pcf_load_font: negative point size\n" )); #endif /* convert from 722.7 decipoints to 72 points per inch */ - bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), - 64 * 7200, - 72270L ); + if ( FT_ABS( prop->value.l ) > 0x504C2L ) /* 0x7FFF * 72270/7200 */ + { + bsize->size = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping point size to value %d\n", + bsize->size )); + } + else + bsize->size = FT_MulDiv( FT_ABS( prop->value.l ), + 64 * 7200, + 72270L ); } prop = pcf_find_property( face, "PIXEL_SIZE" ); @@ -1391,7 +1572,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative pixel size\n" )); #endif - bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + bsize->y_ppem = 0x7FFF << 6; + FT_TRACE0(( "pcf_load_font: clamping pixel size to value %d\n", + bsize->y_ppem )); + } + else + bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6; } prop = pcf_find_property( face, "RESOLUTION_X" ); @@ -1401,7 +1589,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative X resolution\n" )); #endif - resolution_x = FT_ABS( (FT_Short)prop->value.l ); + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + resolution_x = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping X resolution to value %d\n", + resolution_x )); + } + else + resolution_x = FT_ABS( (FT_Short)prop->value.l ); } prop = pcf_find_property( face, "RESOLUTION_Y" ); @@ -1411,7 +1606,14 @@ THE SOFTWARE. if ( prop->value.l < 0 ) FT_TRACE0(( "pcf_load_font: negative Y resolution\n" )); #endif - resolution_y = FT_ABS( (FT_Short)prop->value.l ); + if ( FT_ABS( prop->value.l ) > 0x7FFF ) + { + resolution_y = 0x7FFF; + FT_TRACE0(( "pcf_load_font: clamping Y resolution to value %d\n", + resolution_y )); + } + else + resolution_y = FT_ABS( (FT_Short)prop->value.l ); } if ( bsize->y_ppem == 0 ) |