[pcf] Revise driver.
This commit improves tracing and handling of malformed fonts. In particular, the changes to `pcf_get_properties' fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=379 * src/pcf/pcfread.c (tableNames): Use long names for better readability. (pcf_read_TOC): Allow at most 9 tables. (pcf_get_properties): Allow at most 256 properties. Limit strings array length to 256 * (65536 + 1) bytes. Better tracing. (pcf_get_metric): Trace metric data. (pcf_get_metrics): Allow at most 65536 metrics. Fix comparison of `metrics->ascent' and `metrics->descent' to avoid potential overflow. Better tracing. (pcf_get_bitmaps): Allow at most 65536 bitmaps. Better tracing. (pcf_get_encodings, pcf_get_accel): Better tracing. * src/pcf/pcfdrivr.c (PCF_Glyph_Load): Don't trace `format' details. These are now shown by `pcf_get_bitmaps'.
This commit is contained in:
parent
348d39c68a
commit
8b755445bb
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
||||||
|
2017-01-06 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
|
[pcf] Revise driver.
|
||||||
|
|
||||||
|
This commit improves tracing and handling of malformed fonts. In
|
||||||
|
particular, the changes to `pcf_get_properties' fix
|
||||||
|
|
||||||
|
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=379
|
||||||
|
|
||||||
|
* src/pcf/pcfread.c (tableNames): Use long names for better
|
||||||
|
readability.
|
||||||
|
(pcf_read_TOC): Allow at most 9 tables.
|
||||||
|
(pcf_get_properties): Allow at most 256 properties.
|
||||||
|
Limit strings array length to 256 * (65536 + 1) bytes.
|
||||||
|
Better tracing.
|
||||||
|
(pcf_get_metric): Trace metric data.
|
||||||
|
(pcf_get_metrics): Allow at most 65536 metrics.
|
||||||
|
Fix comparison of `metrics->ascent' and `metrics->descent' to avoid
|
||||||
|
potential overflow.
|
||||||
|
Better tracing.
|
||||||
|
(pcf_get_bitmaps): Allow at most 65536 bitmaps.
|
||||||
|
Better tracing.
|
||||||
|
(pcf_get_encodings, pcf_get_accel): Better tracing.
|
||||||
|
|
||||||
|
* src/pcf/pcfdrivr.c (PCF_Glyph_Load): Don't trace `format' details.
|
||||||
|
These are now shown by `pcf_get_bitmaps'.
|
||||||
|
|
||||||
2017-01-04 Werner Lemberg <wl@gnu.org>
|
2017-01-04 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
* src/pcf/pcfdrivr.c (PCF_Face_Init): Trace compression format.
|
* src/pcf/pcfdrivr.c (PCF_Face_Init): Trace compression format.
|
||||||
|
|
|
@ -524,11 +524,6 @@ THE SOFTWARE.
|
||||||
bitmap->num_grays = 1;
|
bitmap->num_grays = 1;
|
||||||
bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
|
bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
|
||||||
|
|
||||||
FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
|
|
||||||
PCF_BIT_ORDER( face->bitmapsFormat ),
|
|
||||||
PCF_BYTE_ORDER( face->bitmapsFormat ),
|
|
||||||
PCF_GLYPH_PAD( face->bitmapsFormat ) ));
|
|
||||||
|
|
||||||
switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
|
switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -630,19 +625,23 @@ THE SOFTWARE.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
|
if ( prop->value.l > 0x7FFFFFFFL ||
|
||||||
|
prop->value.l < ( -1 - 0x7FFFFFFFL ) )
|
||||||
{
|
{
|
||||||
FT_TRACE1(( "pcf_get_bdf_property: " ));
|
FT_TRACE1(( "pcf_get_bdf_property:" ));
|
||||||
FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
|
FT_TRACE1(( " too large integer 0x%x is truncated\n" ));
|
||||||
}
|
}
|
||||||
/* Apparently, the PCF driver loads all properties as signed integers!
|
|
||||||
* This really doesn't seem to be a problem, because this is
|
/*
|
||||||
* sufficient for any meaningful values.
|
* The PCF driver loads all properties as signed integers.
|
||||||
|
* This really doesn't seem to be a problem, because this is
|
||||||
|
* sufficient for any meaningful values.
|
||||||
*/
|
*/
|
||||||
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
|
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
|
||||||
aproperty->u.integer = (FT_Int32)prop->value.l;
|
aproperty->u.integer = (FT_Int32)prop->value.l;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
return FT_Err_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FT_THROW( Invalid_Argument );
|
return FT_THROW( Invalid_Argument );
|
||||||
|
@ -657,7 +656,7 @@ THE SOFTWARE.
|
||||||
*acharset_encoding = face->charset_encoding;
|
*acharset_encoding = face->charset_encoding;
|
||||||
*acharset_registry = face->charset_registry;
|
*acharset_registry = face->charset_registry;
|
||||||
|
|
||||||
return 0;
|
return FT_Err_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,15 @@ THE SOFTWARE.
|
||||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
static const char* const tableNames[] =
|
static const char* const tableNames[] =
|
||||||
{
|
{
|
||||||
"prop", "accl", "mtrcs", "bmps", "imtrcs",
|
"properties",
|
||||||
"enc", "swidth", "names", "accel"
|
"accelerators",
|
||||||
|
"metrics",
|
||||||
|
"bitmaps",
|
||||||
|
"ink metrics",
|
||||||
|
"encodings",
|
||||||
|
"swidths",
|
||||||
|
"glyph names",
|
||||||
|
"BDF accelerators"
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -109,22 +116,20 @@ THE SOFTWARE.
|
||||||
if ( stream->size < 16 )
|
if ( stream->size < 16 )
|
||||||
return FT_THROW( Invalid_File_Format );
|
return FT_THROW( Invalid_File_Format );
|
||||||
|
|
||||||
/* We need 16 bytes per TOC entry. Additionally, as a */
|
/* we need 16 bytes per TOC entry, */
|
||||||
/* heuristic protection against gzip bombs (i.e., very */
|
/* and there can be most 9 tables */
|
||||||
/* small input files that expand to insanely large */
|
if ( toc->count > ( stream->size >> 4 ) ||
|
||||||
/* files), we limit the number of TOC entries to 1024. */
|
toc->count > 9 )
|
||||||
if ( toc->count > stream->size >> 4 ||
|
|
||||||
toc->count > 1024 )
|
|
||||||
{
|
{
|
||||||
FT_TRACE0(( "pcf_read_TOC: adjusting number of tables"
|
FT_TRACE0(( "pcf_read_TOC: adjusting number of tables"
|
||||||
" (from %d to %d)\n",
|
" (from %d to %d)\n",
|
||||||
toc->count,
|
toc->count,
|
||||||
FT_MIN( stream->size >> 4, 1024 ) ));
|
FT_MIN( stream->size >> 4, 9 ) ));
|
||||||
toc->count = FT_MIN( stream->size >> 4, 1024 );
|
toc->count = FT_MIN( stream->size >> 4, 9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
|
if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
|
||||||
return FT_THROW( Out_Of_Memory );
|
return error;
|
||||||
|
|
||||||
tables = face->toc.tables;
|
tables = face->toc.tables;
|
||||||
for ( n = 0; n < toc->count; n++ )
|
for ( n = 0; n < toc->count; n++ )
|
||||||
|
@ -237,8 +242,8 @@ THE SOFTWARE.
|
||||||
if ( tables[i].type == (FT_UInt)( 1 << j ) )
|
if ( tables[i].type == (FT_UInt)( 1 << j ) )
|
||||||
name = tableNames[j];
|
name = tableNames[j];
|
||||||
|
|
||||||
FT_TRACE4(( " %d: type=%s, format=0x%X, "
|
FT_TRACE4(( " %d: type=%s, format=0x%X,"
|
||||||
"size=%ld (0x%lX), offset=%ld (0x%lX)\n",
|
" size=%ld (0x%lX), offset=%ld (0x%lX)\n",
|
||||||
i, name,
|
i, name,
|
||||||
tables[i].format,
|
tables[i].format,
|
||||||
tables[i].size, tables[i].size,
|
tables[i].size, tables[i].size,
|
||||||
|
@ -348,6 +353,17 @@ THE SOFTWARE.
|
||||||
metric->attributes = 0;
|
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:
|
Exit:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -466,7 +482,7 @@ THE SOFTWARE.
|
||||||
{
|
{
|
||||||
PCF_ParseProperty props = NULL;
|
PCF_ParseProperty props = NULL;
|
||||||
PCF_Property properties = NULL;
|
PCF_Property properties = NULL;
|
||||||
FT_ULong nprops, i;
|
FT_ULong nprops, orig_nprops, i;
|
||||||
FT_ULong format, size;
|
FT_ULong format, size;
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Memory memory = FT_FACE( face )->memory;
|
FT_Memory memory = FT_FACE( face )->memory;
|
||||||
|
@ -486,32 +502,43 @@ THE SOFTWARE.
|
||||||
if ( FT_READ_ULONG_LE( format ) )
|
if ( FT_READ_ULONG_LE( format ) )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
FT_TRACE4(( "pcf_get_properties:\n" ));
|
FT_TRACE4(( "pcf_get_properties:\n"
|
||||||
|
" format: 0x%lX (%s)\n",
|
||||||
FT_TRACE4(( " format = %ld\n", format ));
|
format,
|
||||||
|
PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
|
||||||
|
|
||||||
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
||||||
(void)FT_READ_ULONG( nprops );
|
(void)FT_READ_ULONG( orig_nprops );
|
||||||
else
|
else
|
||||||
(void)FT_READ_ULONG_LE( nprops );
|
(void)FT_READ_ULONG_LE( orig_nprops );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
FT_TRACE4(( " nprop = %d (truncate %d props)\n",
|
FT_TRACE4(( " number of properties: %ld\n", orig_nprops ));
|
||||||
(int)nprops, nprops - (FT_ULong)(int)nprops ));
|
|
||||||
|
|
||||||
nprops = (FT_ULong)(int)nprops;
|
|
||||||
|
|
||||||
/* rough estimate */
|
/* rough estimate */
|
||||||
if ( nprops > size / PCF_PROPERTY_SIZE )
|
if ( orig_nprops > size / PCF_PROPERTY_SIZE )
|
||||||
{
|
{
|
||||||
error = FT_THROW( Invalid_Table );
|
error = FT_THROW( Invalid_Table );
|
||||||
goto Bail;
|
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;
|
face->nprops = (int)nprops;
|
||||||
|
|
||||||
if ( FT_NEW_ARRAY( props, 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 */
|
/* pad the property array */
|
||||||
/* */
|
/* */
|
||||||
/* clever here - nprops is the same as the number of odd-units read, */
|
/* clever here - nprops is the same as the number of odd-units read, */
|
||||||
/* as only isStringProp are odd length (Keith Packard) */
|
/* 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 ) )
|
if ( FT_STREAM_SKIP( i ) )
|
||||||
{
|
{
|
||||||
error = FT_THROW( Invalid_Stream_Skip );
|
error = FT_THROW( Invalid_Stream_Skip );
|
||||||
|
@ -553,15 +589,24 @@ THE SOFTWARE.
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
FT_TRACE4(( " string_size = %ld\n", string_size ));
|
FT_TRACE4(( " string size: %ld\n", string_size ));
|
||||||
|
|
||||||
/* rough estimate */
|
/* rough estimate */
|
||||||
if ( string_size > size - nprops * PCF_PROPERTY_SIZE )
|
if ( string_size > size - orig_nprops * PCF_PROPERTY_SIZE )
|
||||||
{
|
{
|
||||||
error = FT_THROW( Invalid_Table );
|
error = FT_THROW( Invalid_Table );
|
||||||
goto Bail;
|
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 */
|
/* allocate one more byte so that we have a final null byte */
|
||||||
if ( FT_NEW_ARRAY( strings, string_size + 1 ) )
|
if ( FT_NEW_ARRAY( strings, string_size + 1 ) )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
@ -575,6 +620,7 @@ THE SOFTWARE.
|
||||||
|
|
||||||
face->properties = properties;
|
face->properties = properties;
|
||||||
|
|
||||||
|
FT_TRACE4(( "\n" ));
|
||||||
for ( i = 0; i < nprops; i++ )
|
for ( i = 0; i < nprops; i++ )
|
||||||
{
|
{
|
||||||
FT_Long name_offset = props[i].name;
|
FT_Long name_offset = props[i].name;
|
||||||
|
@ -637,7 +683,7 @@ THE SOFTWARE.
|
||||||
FT_Memory memory = FT_FACE( face )->memory;
|
FT_Memory memory = FT_FACE( face )->memory;
|
||||||
FT_ULong format, size;
|
FT_ULong format, size;
|
||||||
PCF_Metric metrics = NULL;
|
PCF_Metric metrics = NULL;
|
||||||
FT_ULong nmetrics, i;
|
FT_ULong nmetrics, orig_nmetrics, i;
|
||||||
|
|
||||||
|
|
||||||
error = pcf_seek_to_table_type( stream,
|
error = pcf_seek_to_table_type( stream,
|
||||||
|
@ -652,6 +698,13 @@ THE SOFTWARE.
|
||||||
if ( FT_READ_ULONG_LE( format ) )
|
if ( FT_READ_ULONG_LE( format ) )
|
||||||
goto Bail;
|
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 ) &&
|
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
|
||||||
!PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
|
!PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
|
||||||
return FT_THROW( Invalid_File_Format );
|
return FT_THROW( Invalid_File_Format );
|
||||||
|
@ -659,61 +712,70 @@ THE SOFTWARE.
|
||||||
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
||||||
{
|
{
|
||||||
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
||||||
(void)FT_READ_ULONG( nmetrics );
|
(void)FT_READ_ULONG( orig_nmetrics );
|
||||||
else
|
else
|
||||||
(void)FT_READ_ULONG_LE( nmetrics );
|
(void)FT_READ_ULONG_LE( orig_nmetrics );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
||||||
(void)FT_READ_USHORT( nmetrics );
|
(void)FT_READ_USHORT( orig_nmetrics );
|
||||||
else
|
else
|
||||||
(void)FT_READ_USHORT_LE( nmetrics );
|
(void)FT_READ_USHORT_LE( orig_nmetrics );
|
||||||
}
|
}
|
||||||
if ( error )
|
if ( error )
|
||||||
return FT_THROW( Invalid_File_Format );
|
return FT_THROW( Invalid_File_Format );
|
||||||
|
|
||||||
face->nmetrics = nmetrics;
|
FT_TRACE4(( " number of metrics: %ld\n", orig_nmetrics ));
|
||||||
|
|
||||||
if ( !nmetrics )
|
|
||||||
return FT_THROW( Invalid_Table );
|
|
||||||
|
|
||||||
FT_TRACE4(( "pcf_get_metrics:\n" ));
|
|
||||||
|
|
||||||
FT_TRACE4(( " number of metrics: %d\n", nmetrics ));
|
|
||||||
|
|
||||||
/* rough estimate */
|
/* rough estimate */
|
||||||
if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
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 );
|
return FT_THROW( Invalid_Table );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
|
if ( orig_nmetrics > size / PCF_COMPRESSED_METRIC_SIZE )
|
||||||
return FT_THROW( Invalid_Table );
|
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 ) )
|
if ( FT_NEW_ARRAY( face->metrics, nmetrics ) )
|
||||||
return FT_THROW( Out_Of_Memory );
|
return error;
|
||||||
|
|
||||||
metrics = face->metrics;
|
metrics = face->metrics;
|
||||||
|
|
||||||
|
FT_TRACE4(( "\n" ));
|
||||||
for ( i = 0; i < nmetrics; i++, metrics++ )
|
for ( i = 0; i < nmetrics; i++, metrics++ )
|
||||||
{
|
{
|
||||||
|
FT_TRACE5(( " idx %ld:", i ));
|
||||||
error = pcf_get_metric( stream, format, metrics );
|
error = pcf_get_metric( stream, format, metrics );
|
||||||
|
|
||||||
metrics->bits = 0;
|
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 )
|
if ( error )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -721,7 +783,7 @@ THE SOFTWARE.
|
||||||
/* compute a glyph's bitmap dimensions, thus setting them to zero in */
|
/* compute a glyph's bitmap dimensions, thus setting them to zero in */
|
||||||
/* case of an error disables this particular glyph only */
|
/* case of an error disables this particular glyph only */
|
||||||
if ( metrics->rightSideBearing < metrics->leftSideBearing ||
|
if ( metrics->rightSideBearing < metrics->leftSideBearing ||
|
||||||
metrics->ascent + metrics->descent < 0 )
|
metrics->ascent < -metrics->descent )
|
||||||
{
|
{
|
||||||
metrics->characterWidth = 0;
|
metrics->characterWidth = 0;
|
||||||
metrics->leftSideBearing = 0;
|
metrics->leftSideBearing = 0;
|
||||||
|
@ -751,7 +813,7 @@ THE SOFTWARE.
|
||||||
FT_Long* offsets = NULL;
|
FT_Long* offsets = NULL;
|
||||||
FT_Long bitmapSizes[GLYPHPADOPTIONS];
|
FT_Long bitmapSizes[GLYPHPADOPTIONS];
|
||||||
FT_ULong format, size;
|
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,
|
error = pcf_seek_to_table_type( stream,
|
||||||
|
@ -769,18 +831,40 @@ THE SOFTWARE.
|
||||||
|
|
||||||
format = FT_GET_ULONG_LE();
|
format = FT_GET_ULONG_LE();
|
||||||
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
||||||
nbitmaps = FT_GET_ULONG();
|
orig_nbitmaps = FT_GET_ULONG();
|
||||||
else
|
else
|
||||||
nbitmaps = FT_GET_ULONG_LE();
|
orig_nbitmaps = FT_GET_ULONG_LE();
|
||||||
|
|
||||||
FT_Stream_ExitFrame( stream );
|
FT_Stream_ExitFrame( stream );
|
||||||
|
|
||||||
|
FT_TRACE4(( "pcf_get_bitmaps:\n"
|
||||||
|
" format: 0x%lX\n"
|
||||||
|
" (%s, %s,\n"
|
||||||
|
" padding=%d bits, scanning=%d bits)\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_SCAN_UNIT_INDEX( format ) ));
|
||||||
|
|
||||||
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
||||||
return FT_THROW( Invalid_File_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 )
|
if ( nbitmaps != face->nmetrics )
|
||||||
return FT_THROW( Invalid_File_Format );
|
return FT_THROW( Invalid_File_Format );
|
||||||
|
@ -788,6 +872,7 @@ THE SOFTWARE.
|
||||||
if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
|
if ( FT_NEW_ARRAY( offsets, nbitmaps ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
FT_TRACE5(( "\n" ));
|
||||||
for ( i = 0; i < nbitmaps; i++ )
|
for ( i = 0; i < nbitmaps; i++ )
|
||||||
{
|
{
|
||||||
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
|
||||||
|
@ -795,7 +880,7 @@ THE SOFTWARE.
|
||||||
else
|
else
|
||||||
(void)FT_READ_LONG_LE( offsets[i] );
|
(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] ));
|
i, offsets[i], offsets[i] ));
|
||||||
}
|
}
|
||||||
if ( error )
|
if ( error )
|
||||||
|
@ -812,17 +897,19 @@ THE SOFTWARE.
|
||||||
|
|
||||||
sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
|
sizebitmaps = (FT_ULong)bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
|
||||||
|
|
||||||
FT_TRACE4(( " padding %d implies a size of %ld\n",
|
FT_TRACE4(( " %ld-bit padding implies a size of %ld\n",
|
||||||
i, bitmapSizes[i] ));
|
8 << i, bitmapSizes[i] ));
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_TRACE4(( " %d bitmaps, padding index %ld\n",
|
FT_TRACE4(( " %ld bitmaps, using %ld-bit padding\n",
|
||||||
nbitmaps,
|
nbitmaps,
|
||||||
PCF_GLYPH_PAD_INDEX( format ) ));
|
8 << PCF_GLYPH_PAD_INDEX( format ) ));
|
||||||
FT_TRACE4(( " bitmap size = %d\n", sizebitmaps ));
|
FT_TRACE4(( " bitmap size: %ld\n", sizebitmaps ));
|
||||||
|
|
||||||
FT_UNUSED( sizebitmaps ); /* only used for debugging */
|
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++ )
|
for ( i = 0; i < nbitmaps; i++ )
|
||||||
{
|
{
|
||||||
/* rough estimate */
|
/* rough estimate */
|
||||||
|
@ -830,7 +917,7 @@ THE SOFTWARE.
|
||||||
( (FT_ULong)offsets[i] > size ) )
|
( (FT_ULong)offsets[i] > size ) )
|
||||||
{
|
{
|
||||||
FT_TRACE0(( "pcf_get_bitmaps:"
|
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
|
else
|
||||||
face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i];
|
face->metrics[i].bits = stream->pos + (FT_ULong)offsets[i];
|
||||||
|
@ -894,10 +981,20 @@ THE SOFTWARE.
|
||||||
|
|
||||||
FT_Stream_ExitFrame( stream );
|
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 ) )
|
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
|
||||||
return FT_THROW( Invalid_File_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 ||
|
if ( firstCol < 0 ||
|
||||||
firstCol > lastCol ||
|
firstCol > lastCol ||
|
||||||
lastCol > 0xFF ||
|
lastCol > 0xFF ||
|
||||||
|
@ -906,21 +1003,18 @@ THE SOFTWARE.
|
||||||
lastRow > 0xFF )
|
lastRow > 0xFF )
|
||||||
return FT_THROW( Invalid_Table );
|
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 ) *
|
nencoding = (FT_ULong)( lastCol - firstCol + 1 ) *
|
||||||
(FT_ULong)( lastRow - firstRow + 1 );
|
(FT_ULong)( lastRow - firstRow + 1 );
|
||||||
|
|
||||||
if ( FT_NEW_ARRAY( encoding, nencoding ) )
|
if ( FT_NEW_ARRAY( encoding, nencoding ) )
|
||||||
return FT_THROW( Out_Of_Memory );
|
return error;
|
||||||
|
|
||||||
error = FT_Stream_EnterFrame( stream, 2 * nencoding );
|
error = FT_Stream_EnterFrame( stream, 2 * nencoding );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
|
FT_TRACE5(( "\n" ));
|
||||||
|
|
||||||
k = 0;
|
k = 0;
|
||||||
for ( i = firstRow; i <= lastRow; i++ )
|
for ( i = firstRow; i <= lastRow; i++ )
|
||||||
{
|
{
|
||||||
|
@ -1029,6 +1123,15 @@ THE SOFTWARE.
|
||||||
if ( FT_READ_ULONG_LE( format ) )
|
if ( FT_READ_ULONG_LE( format ) )
|
||||||
goto Bail;
|
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 ) &&
|
if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) &&
|
||||||
!PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
|
!PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
@ -1044,12 +1147,29 @@ THE SOFTWARE.
|
||||||
goto Bail;
|
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 ));
|
||||||
|
|
||||||
|
FT_TRACE5(( " minbounds:" ));
|
||||||
error = pcf_get_metric( stream,
|
error = pcf_get_metric( stream,
|
||||||
format & ( ~PCF_FORMAT_MASK ),
|
format & ( ~PCF_FORMAT_MASK ),
|
||||||
&(accel->minbounds) );
|
&(accel->minbounds) );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
|
FT_TRACE5(( " maxbounds:" ));
|
||||||
error = pcf_get_metric( stream,
|
error = pcf_get_metric( stream,
|
||||||
format & ( ~PCF_FORMAT_MASK ),
|
format & ( ~PCF_FORMAT_MASK ),
|
||||||
&(accel->maxbounds) );
|
&(accel->maxbounds) );
|
||||||
|
@ -1058,12 +1178,14 @@ THE SOFTWARE.
|
||||||
|
|
||||||
if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
|
if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
|
||||||
{
|
{
|
||||||
|
FT_TRACE5(( " ink minbounds:" ));
|
||||||
error = pcf_get_metric( stream,
|
error = pcf_get_metric( stream,
|
||||||
format & ( ~PCF_FORMAT_MASK ),
|
format & ( ~PCF_FORMAT_MASK ),
|
||||||
&(accel->ink_minbounds) );
|
&(accel->ink_minbounds) );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Bail;
|
goto Bail;
|
||||||
|
|
||||||
|
FT_TRACE5(( " ink maxbounds:" ));
|
||||||
error = pcf_get_metric( stream,
|
error = pcf_get_metric( stream,
|
||||||
format & ( ~PCF_FORMAT_MASK ),
|
format & ( ~PCF_FORMAT_MASK ),
|
||||||
&(accel->ink_maxbounds) );
|
&(accel->ink_maxbounds) );
|
||||||
|
@ -1072,7 +1194,7 @@ THE SOFTWARE.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
|
accel->ink_minbounds = accel->minbounds;
|
||||||
accel->ink_maxbounds = accel->maxbounds;
|
accel->ink_maxbounds = accel->maxbounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue