diff --git a/ChangeLog b/ChangeLog index d7879cd60..dc3128809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2018-07-21 Werner Lemberg + + [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 Move the legacy fuzz target to the `freetype-testing' repository. diff --git a/src/pcf/pcf.h b/src/pcf/pcf.h index f0390cb1e..cb98cc707 100644 --- a/src/pcf/pcf.h +++ b/src/pcf/pcf.h @@ -124,10 +124,14 @@ FT_BEGIN_HEADER } 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_ { FT_Long enc; - FT_UShort glyph; + FT_UShort glyph; /* an index into PCF_Face's `metrics' array */ } PCF_EncodingRec, *PCF_Encoding; @@ -153,7 +157,7 @@ FT_BEGIN_HEADER FT_ULong nencodings; PCF_Encoding encodings; - FT_Short defaultChar; + FT_UShort defaultChar; FT_ULong bitmapsFormat; diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c index c9b7796b1..1a4f4539f 100644 --- a/src/pcf/pcfdrivr.c +++ b/src/pcf/pcfdrivr.c @@ -63,6 +63,10 @@ THE SOFTWARE. #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_ { FT_CMapRec root; @@ -123,7 +127,7 @@ THE SOFTWARE. if ( charcode == code ) { - result = encodings[mid].glyph + 1; + result = encodings[mid].glyph; break; } @@ -161,7 +165,7 @@ THE SOFTWARE. if ( charcode == code ) { - result = encodings[mid].glyph + 1; + result = encodings[mid].glyph; goto Exit; } @@ -175,7 +179,7 @@ THE SOFTWARE. if ( min < cmap->num_encodings ) { charcode = (FT_ULong)encodings[min].enc; - result = encodings[min].glyph + 1; + result = encodings[min].glyph; } Exit: @@ -187,6 +191,7 @@ THE SOFTWARE. } else *acharcode = (FT_UInt32)charcode; + return result; } @@ -512,9 +517,6 @@ THE SOFTWARE. stream = face->root.stream; - if ( glyph_index > 0 ) - glyph_index--; - metric = face->metrics + glyph_index; bitmap->rows = (unsigned int)( metric->ascent + diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c index ffea8209e..06a1a5ec4 100644 --- a/src/pcf/pcfread.c +++ b/src/pcf/pcfread.c @@ -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 pcf_get_encodings( FT_Stream stream, PCF_Face face ) @@ -943,8 +947,10 @@ THE SOFTWARE. int firstCol, lastCol; int firstRow, lastRow; FT_ULong nencoding; - FT_UShort encodingOffset; + FT_UShort defaultCharRow, defaultCharCol; + FT_UShort encodingOffset, defaultCharEncodingOffset; int i, j; + FT_Byte* pos; FT_ULong k; PCF_Encoding encoding = NULL; @@ -964,13 +970,16 @@ THE SOFTWARE. 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 ) { firstCol = FT_GET_SHORT(); lastCol = FT_GET_SHORT(); firstRow = FT_GET_SHORT(); lastRow = FT_GET_SHORT(); - face->defaultChar = FT_GET_SHORT(); + face->defaultChar = FT_GET_USHORT(); } else { @@ -978,7 +987,7 @@ THE SOFTWARE. lastCol = FT_GET_SHORT_LE(); firstRow = 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 ); @@ -1019,6 +1028,47 @@ THE SOFTWARE. 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; for ( i = firstRow; i <= lastRow; i++ ) { @@ -1026,7 +1076,7 @@ THE SOFTWARE. { /* X11's reference implementation uses the equivalent to */ /* `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. */ if ( PCF_BYTE_ORDER( format ) == MSBFirst ) encodingOffset = FT_GET_USHORT(); @@ -1035,6 +1085,11 @@ THE SOFTWARE. if ( encodingOffset != 0xFFFFU ) { + if ( encodingOffset == defaultCharEncodingOffset ) + encodingOffset = 0; + else if ( encodingOffset == 0 ) + encodingOffset = defaultCharEncodingOffset; + encoding[k].enc = i * 256 + j; encoding[k].glyph = encodingOffset;