I had to do this a couple years ago for a work project. I can't post this as it's proprietary, but the spec for TT fonts is here.
I wrote classes for offset table, name record, name table header, and table directory elements such that each class had a static FromStream method.
I also wrote a utility class called BigEndianReader to handle reading data in from a big endian ordered stream, which I'm happy to put here to make your life easier:
public class BigEndianReader
{
public static bool Read(Stream stm, out uint i)
{
int bhihi = stm.ReadByte();
if (bhihi == -1)
{
i = 0;
return false;
}
int bhi = stm.ReadByte();
if (bhi == -1)
{
i = 0;
return false;
}
int blo = stm.ReadByte();
if (blo == -1)
{
i = 0;
return false;
}
int blolo = stm.ReadByte();
if (blolo == -1)
{
i = 0;
return false;
}
i = (uint)((bhihi << 24) | (bhi << 16) | (blo << 8) | blolo);
return true;
}
public static bool Read(Stream stm, out int i)
{
int bhihi = stm.ReadByte();
if (bhihi == -1)
{
i = 0;
return false;
}
int bhi = stm.ReadByte();
if (bhi == -1)
{
i = 0;
return false;
}
int blo = stm.ReadByte();
if (blo == -1)
{
i = 0;
return false;
}
int blolo = stm.ReadByte();
if (blolo == -1)
{
i = 0;
return false;
}
i = ((bhihi << 24) | (bhi << 16) | (blo << 8) | blolo);
return true;
}
public static bool Read(Stream stm, out ushort s)
{
int bhi = stm.ReadByte();
if (bhi == -1)
{
s = 0;
return false;
}
int blo = stm.ReadByte();
if (blo == -1)
{
s = 0;
return false;
}
s = (ushort)(((bhi << 8) | blo) & 0xffff);
return true;
}
public static bool Read(Stream stm, out short s)
{
int bhi = stm.ReadByte();
if (bhi == -1)
{
s = 0;
return false;
}
int blo = stm.ReadByte();
if (blo == -1)
{
s = 0;
return false;
}
s = (short)(((bhi << 8) | blo) & 0xffff);
return true;
}
}
This is not especially elegant, but it's easy enough to use:
int val;
if (!BigEndianReader.Read(stm, out val))
throw new SomeErrorOfSomeKind();
I imagine that if you cared enough you could make this all extension methods on Stream and then your could would read:
int val;
if(!stm.BERead(out val)) // BE prefix for Big Endian
throw new SomeErrorOfSomeKind();