I’m having an issue when parsing TrueType Fonts.
Below is the function responsible for parsing a simple glyph, but it has a problem that I can’t find. I have attached an image that visualises the contours of the glyph. The X and Y coordinates of the glyph points don’t seem to be quite correct. I have checked with many online resources but cannot find a problem.
Yes, I’m aware that TTF’s are big endian.
What am I doing wrong?
#define ON_CURVE_POINT_BIT 0
#define X_SHORT_VECTOR_BIT 1
#define Y_SHORT_VECTOR_BIT 2
#define REPEAT_FLAG_BIT 3
#define X_IS_SAME_OR_POSITIVE_SHORT_VECTOR 4
#define Y_IS_SAME_OR_POSITIVE_SHORT_VECTOR 5
typedef struct
{
short X;
short Y;
bool OnCurve;
} GlyphPoint;
typedef struct
{
bool IsCompound;
short NumOfContours;
short MinX;
short MinY;
short MaxX;
short MaxY;
short unsigned* ContourEndIndices;
short unsigned NumOfPoints;
GlyphPoint* Points;
char unsigned* Flags;
short unsigned NumOfInstructions;
char unsigned* Instructions;
} Glyph;
void Font_ReadSimpleGlyphInternal(FILE* File, Glyph* Result)
{
if (Result->NumOfContours == 0)
{
return;
}
Result->ContourEndIndices = (short unsigned*)Memory_Alloc(Result->NumOfContours * sizeof(short unsigned), 0);
FileReader_ReadUInt16Array(File, true, Result->ContourEndIndices, (int unsigned)Result->NumOfContours);
Result->NumOfPoints = Result->ContourEndIndices[Result->NumOfContours - 1U] + 1U;
Result->Points = (GlyphPoint*)Memory_Alloc(Result->NumOfPoints * sizeof(GlyphPoint), 0);
Result->Flags = (char unsigned*)Memory_Alloc(Result->NumOfPoints, 0);
Result->NumOfInstructions = FileReader_ReadUInt16(File, true);
Result->Instructions = (char unsigned*)Memory_Alloc(Result->NumOfInstructions, 0);
FileReader_ReadUInt8Array(File, Result->Instructions, Result->NumOfInstructions);
for (short unsigned PointIndex = 0; PointIndex < Result->NumOfPoints; PointIndex++)
{
Result->Flags[PointIndex] = FileReader_ReadUInt8(File);
if (IS_BIT_SET(Result->Flags[PointIndex], REPEAT_FLAG_BIT))
{
char unsigned RepeatCount = FileReader_ReadUInt8(File);
for (char unsigned RepeatIndex = 0; RepeatIndex < RepeatCount; RepeatIndex++)
{
Result->Flags[++PointIndex] = Result->Flags[PointIndex - 1];
}
}
}
short CoordX = 0;
short CoordY = 0;
for (short unsigned PointIndex = 0; PointIndex < Result->NumOfPoints; PointIndex++)
{
if (IS_BIT_SET(Result->Flags[PointIndex], X_SHORT_VECTOR_BIT))
{
char CoordOffset = FileReader_ReadInt8(File);
CoordX += IS_BIT_SET(Result->Flags[PointIndex], X_IS_SAME_OR_POSITIVE_SHORT_VECTOR) ? CoordOffset : -CoordOffset;
}
else if (IS_BIT_NOT_SET(Result->Flags[PointIndex], X_IS_SAME_OR_POSITIVE_SHORT_VECTOR))
{
CoordX += FileReader_ReadInt16(File, true);
}
Result->Points[PointIndex].X = CoordX;
Result->Points[PointIndex].OnCurve = IS_BIT_SET(Result->Flags[PointIndex], ON_CURVE_POINT_BIT);
}
for (short unsigned PointIndex = 0; PointIndex < Result->NumOfPoints; PointIndex++)
{
if (IS_BIT_SET(Result->Flags[PointIndex], Y_SHORT_VECTOR_BIT))
{
char CoordOffset = FileReader_ReadInt8(File);
CoordY += IS_BIT_SET(Result->Flags[PointIndex], Y_IS_SAME_OR_POSITIVE_SHORT_VECTOR) ? CoordOffset : -CoordOffset;
}
else if (IS_BIT_NOT_SET(Result->Flags[PointIndex], Y_IS_SAME_OR_POSITIVE_SHORT_VECTOR))
{
CoordY += FileReader_ReadInt16(File, true);
}
Result->Points[PointIndex].Y = CoordY;
Result->Points[PointIndex].OnCurve = IS_BIT_SET(Result->Flags[PointIndex], ON_CURVE_POINT_BIT);
}
}
You need to sign in to view this answers