[pcf] Fix handling of the undefined glyph.

This change makes the driver use the `defaultChar' property of PCF
files.

* src/pcf/pcf.h (PCF_FaceRec): Change type of `defaultChar' to
unsigned.

* src/pcf/pcfread.c (pcf_get_encodings): Read `defaultChar' as
unsigned.
Validate `defaultChar'.
If `defaultChar' doesn't point to glyph index zero, swap glyphs with
index zero and index `defaultChar' and adjust the encodings
accordingly.

* src/pcf/pcfdrivr.c (pcf_cmap_char_index, pcf_cmap_char_next,
PCF_Glyph_Load): Undo change from 2002-06-16 which always enforced
the first character in the font to be the default character.
This commit is contained in:
Werner Lemberg 2018-07-21 23:45:32 +02:00
parent a2370f21b5
commit cba72a0b0f
4 changed files with 94 additions and 12 deletions

View File

@ -1,3 +1,24 @@
2018-07-21 Werner Lemberg <wl@gnu.org>
[pcf] Fix handling of the undefined glyph.
This change makes the driver use the `defaultChar' property of PCF
files.
* src/pcf/pcf.h (PCF_FaceRec): Change type of `defaultChar' to
unsigned.
* src/pcf/pcfread.c (pcf_get_encodings): Read `defaultChar' as
unsigned.
Validate `defaultChar'.
If `defaultChar' doesn't point to glyph index zero, swap glyphs with
index zero and index `defaultChar' and adjust the encodings
accordingly.
* src/pcf/pcfdrivr.c (pcf_cmap_char_index, pcf_cmap_char_next,
PCF_Glyph_Load): Undo change from 2002-06-16 which always enforced
the first character in the font to be the default character.
2018-07-20 Armin Hasitzka <prince.cherusker@gmail.com> 2018-07-20 Armin Hasitzka <prince.cherusker@gmail.com>
Move the legacy fuzz target to the `freetype-testing' repository. Move the legacy fuzz target to the `freetype-testing' repository.

View File

@ -124,10 +124,14 @@ FT_BEGIN_HEADER
} PCF_AccelRec, *PCF_Accel; } PCF_AccelRec, *PCF_Accel;
/*
* This file uses X11 terminology for PCF data; an `encoding' in X11 speak
* is the same as a `character code' in FreeType speak.
*/
typedef struct PCF_EncodingRec_ typedef struct PCF_EncodingRec_
{ {
FT_Long enc; FT_Long enc;
FT_UShort glyph; FT_UShort glyph; /* an index into PCF_Face's `metrics' array */
} PCF_EncodingRec, *PCF_Encoding; } PCF_EncodingRec, *PCF_Encoding;
@ -153,7 +157,7 @@ FT_BEGIN_HEADER
FT_ULong nencodings; FT_ULong nencodings;
PCF_Encoding encodings; PCF_Encoding encodings;
FT_Short defaultChar; FT_UShort defaultChar;
FT_ULong bitmapsFormat; FT_ULong bitmapsFormat;

View File

@ -63,6 +63,10 @@ THE SOFTWARE.
#define FT_COMPONENT trace_pcfdriver #define FT_COMPONENT trace_pcfdriver
/*
* This file uses X11 terminology for PCF data; an `encoding' in X11 speak
* is the same as a `character code' in FreeType speak.
*/
typedef struct PCF_CMapRec_ typedef struct PCF_CMapRec_
{ {
FT_CMapRec root; FT_CMapRec root;
@ -123,7 +127,7 @@ THE SOFTWARE.
if ( charcode == code ) if ( charcode == code )
{ {
result = encodings[mid].glyph + 1; result = encodings[mid].glyph;
break; break;
} }
@ -161,7 +165,7 @@ THE SOFTWARE.
if ( charcode == code ) if ( charcode == code )
{ {
result = encodings[mid].glyph + 1; result = encodings[mid].glyph;
goto Exit; goto Exit;
} }
@ -175,7 +179,7 @@ THE SOFTWARE.
if ( min < cmap->num_encodings ) if ( min < cmap->num_encodings )
{ {
charcode = (FT_ULong)encodings[min].enc; charcode = (FT_ULong)encodings[min].enc;
result = encodings[min].glyph + 1; result = encodings[min].glyph;
} }
Exit: Exit:
@ -187,6 +191,7 @@ THE SOFTWARE.
} }
else else
*acharcode = (FT_UInt32)charcode; *acharcode = (FT_UInt32)charcode;
return result; return result;
} }
@ -512,9 +517,6 @@ THE SOFTWARE.
stream = face->root.stream; stream = face->root.stream;
if ( glyph_index > 0 )
glyph_index--;
metric = face->metrics + glyph_index; metric = face->metrics + glyph_index;
bitmap->rows = (unsigned int)( metric->ascent + bitmap->rows = (unsigned int)( metric->ascent +

View File

@ -933,6 +933,10 @@ THE SOFTWARE.
} }
/*
* This file uses X11 terminology for PCF data; an `encoding' in X11 speak
* is the same as a character code in FreeType speak.
*/
static FT_Error static FT_Error
pcf_get_encodings( FT_Stream stream, pcf_get_encodings( FT_Stream stream,
PCF_Face face ) PCF_Face face )
@ -943,8 +947,10 @@ THE SOFTWARE.
int firstCol, lastCol; int firstCol, lastCol;
int firstRow, lastRow; int firstRow, lastRow;
FT_ULong nencoding; FT_ULong nencoding;
FT_UShort encodingOffset; FT_UShort defaultCharRow, defaultCharCol;
FT_UShort encodingOffset, defaultCharEncodingOffset;
int i, j; int i, j;
FT_Byte* pos;
FT_ULong k; FT_ULong k;
PCF_Encoding encoding = NULL; PCF_Encoding encoding = NULL;
@ -964,13 +970,16 @@ THE SOFTWARE.
format = FT_GET_ULONG_LE(); format = FT_GET_ULONG_LE();
/* X11's reference implementation uses the equivalent to */
/* `FT_GET_SHORT' for `defaultChar', however this doesn't */
/* make sense for most encodings. */
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
{ {
firstCol = FT_GET_SHORT(); firstCol = FT_GET_SHORT();
lastCol = FT_GET_SHORT(); lastCol = FT_GET_SHORT();
firstRow = FT_GET_SHORT(); firstRow = FT_GET_SHORT();
lastRow = FT_GET_SHORT(); lastRow = FT_GET_SHORT();
face->defaultChar = FT_GET_SHORT(); face->defaultChar = FT_GET_USHORT();
} }
else else
{ {
@ -978,7 +987,7 @@ THE SOFTWARE.
lastCol = FT_GET_SHORT_LE(); lastCol = FT_GET_SHORT_LE();
firstRow = FT_GET_SHORT_LE(); firstRow = FT_GET_SHORT_LE();
lastRow = FT_GET_SHORT_LE(); lastRow = FT_GET_SHORT_LE();
face->defaultChar = FT_GET_SHORT_LE(); face->defaultChar = FT_GET_USHORT_LE();
} }
FT_Stream_ExitFrame( stream ); FT_Stream_ExitFrame( stream );
@ -1019,6 +1028,47 @@ THE SOFTWARE.
FT_TRACE5(( "\n" )); FT_TRACE5(( "\n" ));
defaultCharRow = face->defaultChar >> 8;
defaultCharCol = face->defaultChar & 0xFF;
/* validate default character */
if ( defaultCharRow < (FT_UShort)firstRow ||
defaultCharRow > (FT_UShort)lastRow ||
defaultCharCol < (FT_UShort)firstCol ||
defaultCharCol > (FT_UShort)lastCol )
{
face->defaultChar = firstRow * 256 + firstCol;
FT_TRACE0(( "pcf_get_encodings:"
" Invalid default character set to %d\n",
face->defaultChar ));
}
/* FreeType mandates that glyph index 0 is the `undefined glyph', */
/* which PCF calls the `default character'. For this reason, we */
/* swap the positions of glyph index 0 and the index corresponding */
/* to `defaultChar' in case they are different. */
/* `stream->cursor' still points at the beginning of the frame; */
/* we can thus easily get the offset to the default character */
pos = stream->cursor +
2 * ( ( defaultCharRow - (FT_UShort)firstRow ) * 256 +
defaultCharCol - (FT_UShort)firstCol );
if ( PCF_BYTE_ORDER( format ) == MSBFirst )
defaultCharEncodingOffset = FT_PEEK_USHORT( pos );
else
defaultCharEncodingOffset = FT_PEEK_USHORT_LE( pos );
if ( defaultCharEncodingOffset )
{
/* do the swapping */
PCF_MetricRec tmp = face->metrics[defaultCharEncodingOffset];
face->metrics[defaultCharEncodingOffset] = face->metrics[0];
face->metrics[0] = tmp;
}
k = 0; k = 0;
for ( i = firstRow; i <= lastRow; i++ ) for ( i = firstRow; i <= lastRow; i++ )
{ {
@ -1026,7 +1076,7 @@ THE SOFTWARE.
{ {
/* X11's reference implementation uses the equivalent to */ /* X11's reference implementation uses the equivalent to */
/* `FT_GET_SHORT', however PCF fonts with more than 32768 */ /* `FT_GET_SHORT', however PCF fonts with more than 32768 */
/* characters (e.g. `unifont.pcf') clearly show that an */ /* characters (e.g., `unifont.pcf') clearly show that an */
/* unsigned value is needed. */ /* unsigned value is needed. */
if ( PCF_BYTE_ORDER( format ) == MSBFirst ) if ( PCF_BYTE_ORDER( format ) == MSBFirst )
encodingOffset = FT_GET_USHORT(); encodingOffset = FT_GET_USHORT();
@ -1035,6 +1085,11 @@ THE SOFTWARE.
if ( encodingOffset != 0xFFFFU ) if ( encodingOffset != 0xFFFFU )
{ {
if ( encodingOffset == defaultCharEncodingOffset )
encodingOffset = 0;
else if ( encodingOffset == 0 )
encodingOffset = defaultCharEncodingOffset;
encoding[k].enc = i * 256 + j; encoding[k].enc = i * 256 + j;
encoding[k].glyph = encodingOffset; encoding[k].glyph = encodingOffset;