ref: cba72a0b0f0256e61af8dc6cb1924b143b127dde
parent: a2370f21b5c42dc077ee7be3d5a5d3cb0733d7d7
author: Werner Lemberg <[email protected]>
date: Sat Jul 21 19:45:32 EDT 2018
[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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2018-07-21 Werner Lemberg <[email protected]>
+
+ [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 <[email protected]>
Move the legacy fuzz target to the `freetype-testing' repository.
--- a/src/pcf/pcf.h
+++ b/src/pcf/pcf.h
@@ -124,10 +124,14 @@
} 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_ULong nencodings;
PCF_Encoding encodings;
- FT_Short defaultChar;
+ FT_UShort defaultChar;
FT_ULong bitmapsFormat;
--- a/src/pcf/pcfdrivr.c
+++ b/src/pcf/pcfdrivr.c
@@ -63,6 +63,10 @@
#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 @@
if ( charcode == code )
{
- result = encodings[mid].glyph + 1;
+ result = encodings[mid].glyph;
break;
}
@@ -161,7 +165,7 @@
if ( charcode == code )
{
- result = encodings[mid].glyph + 1;
+ result = encodings[mid].glyph;
goto Exit;
}
@@ -175,7 +179,7 @@
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 @@
}
else
*acharcode = (FT_UInt32)charcode;
+
return result;
}
@@ -511,9 +516,6 @@
}
stream = face->root.stream;
-
- if ( glyph_index > 0 )
- glyph_index--;
metric = face->metrics + glyph_index;
--- a/src/pcf/pcfread.c
+++ b/src/pcf/pcfread.c
@@ -933,6 +933,10 @@
}
+ /*
+ * 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 @@
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,6 +970,9 @@
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();
@@ -970,7 +979,7 @@
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 @@
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 @@
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 @@
{
/* 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 @@
if ( encodingOffset != 0xFFFFU )
{
+ if ( encodingOffset == defaultCharEncodingOffset )
+ encodingOffset = 0;
+ else if ( encodingOffset == 0 )
+ encodingOffset = defaultCharEncodingOffset;
+
encoding[k].enc = i * 256 + j;
encoding[k].glyph = encodingOffset;