网上有个Java版本的,我拿过来改了个C#版的,废话不多说,直接上代码
public class TTFParser
{
public static int COPYRIGHT = 0;
public static int FAMILY_NAME = 1;
public static int FONT_SUBFAMILY_NAME = 2;
public static int UNIQUE_FONT_IDENTIFIER = 3;
public static int FULL_FONT_NAME = 4;
public static int VERSION = 5;
public static int POSTSCRIPT_NAME = 6;
public static int TRADEMARK = 7;
public static int MANUFACTURER = 8;
public static int DESIGNER = 9;
public static int DESCRIPTION = 10;
public static int URL_VENDOR = 11;
public static int URL_DESIGNER = 12;
public static int LICENSE_DESCRIPTION = 13;
public static int LICENSE_INFO_URL = 14;
private Dictionary fontProperties = new Dictionary();
/**
* 获取ttf font name
* @return
*/
public string FontName
{
get
{
if (fontProperties.ContainsKey(FULL_FONT_NAME))
{
return fontProperties[FULL_FONT_NAME];
}
else if (fontProperties.ContainsKey(FAMILY_NAME))
{
return fontProperties[FAMILY_NAME];
}
else
{
return null;
}
}
}
/**
* 获取ttf属性
* @param nameID 属性标记,见静态变量
* @return 属性值
*/
public string GetFontPropertie(int nameID)
{
if (fontProperties.ContainsKey(nameID))
{
return fontProperties[nameID];
}
else
{
return null;
}
}
/**
* 获取ttf属性集合
* @return 属性集合(Dictionary)
*/
public Dictionary FontProperties
{
get { return fontProperties; }
}
/**
* 执行解析
* @param fileName ttf文件名
* @throws IOException
*/
public void Parse(string fileName)
{
fontProperties.Clear();
FileStream f = null;
f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
ParseInner(f);
f.Close();
}
private short ReadShort(FileStream stream)
{
byte[] buffer = new byte[2];
if (stream.Read(buffer, 0, buffer.Length) < buffer.Length)
return -1;
return (short)(buffer[0] << 8 | buffer[1]);
}
private int ReadInt(FileStream stream)
{
byte[] buffer = new byte[4];
if (stream.Read(buffer, 0, buffer.Length) < buffer.Length)
return -1;
return (int)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
}
private void ParseInner(FileStream stream)
{
int majorVersion = ReadShort(stream);
int minorVersion = ReadShort(stream);
int numOfTables = ReadShort(stream);
if (majorVersion != 1 || minorVersion != 0)
{
return;
}
// jump to TableDirectory struct
stream.Seek(12, SeekOrigin.Begin);
bool found = false;
byte[] buff = new byte[4];
TableDirectory tableDirectory = new TableDirectory();
for (int i = 0; i < numOfTables; i++)
{
stream.Read(buff, 0, buff.Length);
tableDirectory.name = Encoding.Default.GetString(buff);
tableDirectory.checkSum = ReadInt(stream);
tableDirectory.offset = ReadInt(stream);
tableDirectory.length = ReadInt(stream);
if ("name".Equals(tableDirectory.name, StringComparison.CurrentCultureIgnoreCase))
{
found = true;
break;
}
else if (tableDirectory.name == null || tableDirectory.name.Length == 0)
{
break;
}
}
// not found table of name
if (!found)
{
return;
}
stream.Seek(tableDirectory.offset, SeekOrigin.Begin);
NameTableHeader nameTableHeader = new NameTableHeader();
nameTableHeader.fSelector = ReadShort(stream);
nameTableHeader.nRCount = ReadShort(stream);
nameTableHeader.storageOffset = ReadShort(stream);
NameRecord nameRecord = new NameRecord();
for (int i = 0; i < nameTableHeader.nRCount; i++)
{
nameRecord.platformID = ReadShort(stream);
nameRecord.encodingID = ReadShort(stream);
nameRecord.languageID = ReadShort(stream);
nameRecord.nameID = ReadShort(stream);
nameRecord.stringLength = ReadShort(stream);
nameRecord.stringOffset = ReadShort(stream);
long pos = stream.Position;
byte[] bf = new byte[nameRecord.stringLength];
long vpos = tableDirectory.offset + nameRecord.stringOffset + nameTableHeader.storageOffset;
stream.Seek(vpos, SeekOrigin.Begin);
stream.Read(bf, 0, bf.Length);
string temp = Encoding.BigEndianUnicode.GetString(bf);
if (fontProperties.ContainsKey(nameRecord.nameID))
fontProperties[nameRecord.nameID] = temp;
else
fontProperties.Add(nameRecord.nameID, temp);
stream.Seek(pos, SeekOrigin.Begin);
}
}
public override string ToString()
{
return fontProperties.ToString();
}
private class TableDirectory
{
public string name; //table name
public int checkSum; //Check sum
public int offset; //Offset from beginning of file
public int length; //length of the table in bytes
public override string ToString()
{
return name;
}
}
private class NameTableHeader
{
public int fSelector; //format selector. Always 0
public int nRCount; //Name Records count
public int storageOffset; //Offset for strings storage,
}
private class NameRecord
{
public int platformID;
public int encodingID;
public int languageID;
public int nameID;
public int stringLength;
public int stringOffset; //from start of storage area
public override string ToString()
{
return nameID.ToString();
}
}
}