static public FontFamily FromPath(string fontFilePath) { string FontName = string.Empty; string FontSubFamily = string.Empty; string encStr = "UTF-8"; string strRet = string.Empty; using (FileStream fs = new FileStream(fontFilePath, FileMode.Open, FileAccess.Read)) { TT_OFFSET_TABLE ttOffsetTable = new TT_OFFSET_TABLE() { uMajorVersion = ReadUShort(fs), uMinorVersion = ReadUShort(fs), uNumOfTables = ReadUShort(fs), uSearchRange = ReadUShort(fs), uEntrySelector = ReadUShort(fs), uRangeShift = ReadUShort(fs), }; TT_TABLE_DIRECTORY tblDir = new TT_TABLE_DIRECTORY(); bool found = false; for (int i = 0; i <= ttOffsetTable.uNumOfTables; i++) { tblDir = new TT_TABLE_DIRECTORY(); tblDir.Initialize(); fs.Read(tblDir.szTag, 0, tblDir.szTag.Length); tblDir.uCheckSum = ReadULong(fs); tblDir.uOffset = ReadULong(fs); tblDir.uLength = ReadULong(fs); Encoding enc = Encoding.GetEncoding(encStr); string s = enc.GetString(tblDir.szTag); if (s.CompareTo("name") == 0) { found = true; break; } } if (!found) { return(null); } fs.Seek(tblDir.uOffset, SeekOrigin.Begin); TT_NAME_TABLE_HEADER ttNTHeader = new TT_NAME_TABLE_HEADER { uFSelector = ReadUShort(fs), uNRCount = ReadUShort(fs), uStorageOffset = ReadUShort(fs) }; TT_NAME_RECORD ttRecord = new TT_NAME_RECORD(); for (int j = 0; j <= ttNTHeader.uNRCount; j++) { ttRecord = new TT_NAME_RECORD() { uPlatformID = ReadUShort(fs), uEncodingID = ReadUShort(fs), uLanguageID = ReadUShort(fs), uNameID = ReadUShort(fs), uStringLength = ReadUShort(fs), uStringOffset = ReadUShort(fs) }; if (ttRecord.uNameID > 2) { break; } long nPos = fs.Position; fs.Seek(tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, SeekOrigin.Begin); byte[] buf = new byte[ttRecord.uStringLength]; fs.Read(buf, 0, ttRecord.uStringLength); Encoding enc; if (ttRecord.uEncodingID == 3 || ttRecord.uEncodingID == 1) { enc = Encoding.BigEndianUnicode; } else { enc = Encoding.UTF8; } strRet = enc.GetString(buf); if (ttRecord.uNameID == 1) { FontName = strRet; } if (ttRecord.uNameID == 2) { FontSubFamily = strRet; } fs.Seek(nPos, SeekOrigin.Begin); } return(new FontFamily(FontName, FontSubFamily, fontFilePath)); } }
//TODO: merge this to Typography //from http://stackoverflow.com/questions/3633000/net-enumerate-winforms-font-styles // https://www.microsoft.com/Typography/OTSpec/name.htm public static InstalledFont GetFontDetails(string fontFilePath) { //TODO: review here //merge to the Typography? string fontName = string.Empty; string fontSubFamily = string.Empty; string strRet = string.Empty; using (FileStream fs = new FileStream(fontFilePath, FileMode.Open, FileAccess.Read)) { TT_OFFSET_TABLE ttOffsetTable = new TT_OFFSET_TABLE() { uMajorVersion = ReadUShort(fs), uMinorVersion = ReadUShort(fs), uNumOfTables = ReadUShort(fs), uSearchRange = ReadUShort(fs), uEntrySelector = ReadUShort(fs), uRangeShift = ReadUShort(fs), }; if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0) { return(null); } TT_TABLE_DIRECTORY tblDir = new TT_TABLE_DIRECTORY(); bool found = false; Encoding enc = Encoding.UTF8; for (int i = 0; i <= ttOffsetTable.uNumOfTables; i++) { tblDir = new TT_TABLE_DIRECTORY(); tblDir.Initialize(); fs.Read(tblDir.szTag, 0, tblDir.szTag.Length); tblDir.uCheckSum = ReadULong(fs); tblDir.uOffset = ReadULong(fs); tblDir.uLength = ReadULong(fs); string s = enc.GetString(tblDir.szTag); if (s.CompareTo("name") == 0) { found = true; break; } } if (!found) { return(null); } fs.Seek(tblDir.uOffset, SeekOrigin.Begin); TT_NAME_TABLE_HEADER ttNTHeader = new TT_NAME_TABLE_HEADER { uFSelector = ReadUShort(fs), uNRCount = ReadUShort(fs), uStorageOffset = ReadUShort(fs) }; TT_NAME_RECORD ttRecord = new TT_NAME_RECORD(); for (int j = 0; j <= ttNTHeader.uNRCount; j++) { ttRecord = new TT_NAME_RECORD() { uPlatformID = ReadUShort(fs), uEncodingID = ReadUShort(fs), uLanguageID = ReadUShort(fs), uNameID = ReadUShort(fs), uStringLength = ReadUShort(fs), uStringOffset = ReadUShort(fs) }; //if (ttRecord.uNameID > 2) //{ //} long nPos = fs.Position; fs.Seek(tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, SeekOrigin.Begin); byte[] buf = new byte[ttRecord.uStringLength]; fs.Read(buf, 0, ttRecord.uStringLength); Encoding enc2; if (ttRecord.uEncodingID == 3 || ttRecord.uEncodingID == 1) { enc2 = Encoding.BigEndianUnicode; } else { enc2 = Encoding.UTF8; } strRet = enc2.GetString(buf); switch (ttRecord.uNameID) { case 1: fontName = strRet; break; case 2: fontSubFamily = strRet; break; default: break; } fs.Seek(nPos, SeekOrigin.Begin); } return(new InstalledFont(fontName, fontSubFamily, fontFilePath)); } }
private string GetFontName(string fontPath) { string result = ""; FileStream fs = new FileStream(fontPath, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs, Encoding.UTF8); byte[] buff = r.ReadBytes(Marshal.SizeOf(ttResult)); buff = BigEndian(buff); IntPtr ptr = Marshal.AllocHGlobal(buff.Length); Marshal.Copy(buff, 0x0, ptr, buff.Length); ttResult = (TT_OFFSET_TABLE)Marshal.PtrToStructure(ptr, typeof(TT_OFFSET_TABLE)); Marshal.FreeHGlobal(ptr); //Must be maj =1 minor = 0 if (ttResult.uMajorVersion != 1 || ttResult.uMinorVersion != 0) return ""; bool bFound = false; tbName = new TT_TABLE_DIRECTORY(); for (int i = 0; i < ttResult.uNumOfTables; i++) { byte[] bNameTable = r.ReadBytes(Marshal.SizeOf(tbName)); IntPtr ptrName = Marshal.AllocHGlobal(bNameTable.Length); Marshal.Copy(bNameTable, 0x0, ptrName, bNameTable.Length); tbName = (TT_TABLE_DIRECTORY)Marshal.PtrToStructure(ptrName, typeof(TT_TABLE_DIRECTORY)); Marshal.FreeHGlobal(ptrName); string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString(); if (szName != null) { if (szName.ToString() == "name") { bFound = true; byte [] btLength = BitConverter.GetBytes(tbName.uLength); byte [] btOffset = BitConverter.GetBytes(tbName.uOffset); Array.Reverse(btLength); Array.Reverse(btOffset); tbName.uLength = BitConverter.ToUInt32(btLength, 0); tbName.uOffset = BitConverter.ToUInt32(btOffset, 0); break; } } } if (bFound) { fs.Position = tbName.uOffset; byte[] btNTHeader = r.ReadBytes(Marshal.SizeOf(ttNTResult)); btNTHeader = BigEndian(btNTHeader); IntPtr ptrNTHeader = Marshal.AllocHGlobal(btNTHeader.Length); Marshal.Copy(btNTHeader, 0x0, ptrNTHeader, btNTHeader.Length); ttNTResult = (TT_NAME_TABLE_HEADER)Marshal.PtrToStructure(ptrNTHeader, typeof(TT_NAME_TABLE_HEADER)); Marshal.FreeHGlobal(ptrNTHeader); bFound = false; for (int i = 0; i < ttNTResult.uNRCount; i++) { byte[] btNMRecord = r.ReadBytes(Marshal.SizeOf(ttNMResult)); btNMRecord = BigEndian(btNMRecord); IntPtr ptrNMRecord = Marshal.AllocHGlobal(btNMRecord.Length); Marshal.Copy(btNMRecord, 0x0, ptrNMRecord, btNMRecord.Length); ttNMResult = (TT_NAME_RECORD)Marshal.PtrToStructure(ptrNMRecord, typeof(TT_NAME_RECORD)); Marshal.FreeHGlobal(ptrNMRecord); // this is where the font name is recovered // to get the font family name (not incl 'bold' etc) use ttNMResult.uNameID == 1 // see http://www.microsoft.com/OpenType/OTSpec/name.htm if (ttNMResult.uNameID == 4) //if (ttNMResult.uNameID == 1) { long fPos = fs.Position; fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset; char[] szResult = r.ReadChars(ttNMResult.uStringLength); if (szResult.Length != 0) { // some fonts are \0 A \0 r \0 i \0 a \0 l.... UTf8 encoding doesn't help if (szResult[0] == '\0') { int count = 0; char[] temp = new char[szResult.Length / 2]; for (int j = 1; j < szResult.Length; j += 2) { temp[count++] = szResult[j]; } szResult = temp; } result = new String(szResult); break; } } } } return result; }
static public FontFamily FromPath(string fontFilePath) { string FontName = string.Empty; string FontSubFamily = string.Empty; string encStr = "UTF-8"; string strRet = string.Empty; using (FileStream fs = new FileStream(fontFilePath, FileMode.Open, FileAccess.Read)) { TT_OFFSET_TABLE ttOffsetTable = new TT_OFFSET_TABLE() { uMajorVersion = ReadUShort(fs), uMinorVersion = ReadUShort(fs), uNumOfTables = ReadUShort(fs), uSearchRange = ReadUShort(fs), uEntrySelector = ReadUShort(fs), uRangeShift = ReadUShort(fs), }; TT_TABLE_DIRECTORY tblDir = new TT_TABLE_DIRECTORY(); bool found = false; for (int i = 0; i <= ttOffsetTable.uNumOfTables; i++) { tblDir = new TT_TABLE_DIRECTORY(); tblDir.Initialize(); fs.Read(tblDir.szTag, 0, tblDir.szTag.Length); tblDir.uCheckSum = ReadULong(fs); tblDir.uOffset = ReadULong(fs); tblDir.uLength = ReadULong(fs); Encoding enc = Encoding.GetEncoding(encStr); string s = enc.GetString(tblDir.szTag); if (s.CompareTo("name") == 0) { found = true; break; } } if (!found) return null; fs.Seek(tblDir.uOffset, SeekOrigin.Begin); TT_NAME_TABLE_HEADER ttNTHeader = new TT_NAME_TABLE_HEADER { uFSelector = ReadUShort(fs), uNRCount = ReadUShort(fs), uStorageOffset = ReadUShort(fs) }; TT_NAME_RECORD ttRecord = new TT_NAME_RECORD(); for (int j = 0; j <= ttNTHeader.uNRCount; j++) { ttRecord = new TT_NAME_RECORD() { uPlatformID = ReadUShort(fs), uEncodingID = ReadUShort(fs), uLanguageID = ReadUShort(fs), uNameID = ReadUShort(fs), uStringLength = ReadUShort(fs), uStringOffset = ReadUShort(fs) }; if (ttRecord.uNameID > 2) { break; } long nPos = fs.Position; fs.Seek(tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, SeekOrigin.Begin); byte[] buf = new byte[ttRecord.uStringLength]; fs.Read(buf, 0, ttRecord.uStringLength); Encoding enc; if (ttRecord.uEncodingID == 3 || ttRecord.uEncodingID == 1) { enc = Encoding.BigEndianUnicode; } else { enc = Encoding.UTF8; } strRet = enc.GetString(buf); if (ttRecord.uNameID == 1) { FontName = strRet; } if (ttRecord.uNameID == 2) { FontSubFamily = strRet; } fs.Seek(nPos, SeekOrigin.Begin); } return new FontFamily(FontName, FontSubFamily, fontFilePath); } }
private string GetFontName(string fontPath) { string result = ""; FileStream fs = new FileStream(fontPath, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs, Encoding.UTF8); try { byte[] buff = r.ReadBytes(Marshal.SizeOf(ttResult)); buff = BigEndian(buff); IntPtr ptr = Marshal.AllocHGlobal(buff.Length); Marshal.Copy(buff, 0x0, ptr, buff.Length); ttResult = (TT_OFFSET_TABLE)Marshal.PtrToStructure(ptr, typeof(TT_OFFSET_TABLE)); Marshal.FreeHGlobal(ptr); //Must be maj =1 minor = 0 if (ttResult.uMajorVersion != 1 || ttResult.uMinorVersion != 0) { return(""); } bool bFound = false; tbName = new TT_TABLE_DIRECTORY(); for (int i = 0; i < ttResult.uNumOfTables; i++) { byte[] bNameTable = r.ReadBytes(Marshal.SizeOf(tbName)); IntPtr ptrName = Marshal.AllocHGlobal(bNameTable.Length); Marshal.Copy(bNameTable, 0x0, ptrName, bNameTable.Length); tbName = (TT_TABLE_DIRECTORY)Marshal.PtrToStructure(ptrName, typeof(TT_TABLE_DIRECTORY)); Marshal.FreeHGlobal(ptrName); string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString(); if (szName != null) { if (szName.ToString() == "name") { bFound = true; byte[] btLength = BitConverter.GetBytes(tbName.uLength); byte[] btOffset = BitConverter.GetBytes(tbName.uOffset); Array.Reverse(btLength); Array.Reverse(btOffset); tbName.uLength = BitConverter.ToUInt32(btLength, 0); tbName.uOffset = BitConverter.ToUInt32(btOffset, 0); break; } } } if (bFound) { fs.Position = tbName.uOffset; byte[] btNTHeader = r.ReadBytes(Marshal.SizeOf(ttNTResult)); btNTHeader = BigEndian(btNTHeader); IntPtr ptrNTHeader = Marshal.AllocHGlobal(btNTHeader.Length); Marshal.Copy(btNTHeader, 0x0, ptrNTHeader, btNTHeader.Length); ttNTResult = (TT_NAME_TABLE_HEADER)Marshal.PtrToStructure(ptrNTHeader, typeof(TT_NAME_TABLE_HEADER)); Marshal.FreeHGlobal(ptrNTHeader); bFound = false; for (int i = 0; i < ttNTResult.uNRCount; i++) { byte[] btNMRecord = r.ReadBytes(Marshal.SizeOf(ttNMResult)); btNMRecord = BigEndian(btNMRecord); IntPtr ptrNMRecord = Marshal.AllocHGlobal(btNMRecord.Length); Marshal.Copy(btNMRecord, 0x0, ptrNMRecord, btNMRecord.Length); ttNMResult = (TT_NAME_RECORD)Marshal.PtrToStructure(ptrNMRecord, typeof(TT_NAME_RECORD)); Marshal.FreeHGlobal(ptrNMRecord); // this is where the font name is recovered // to get the font family name (not incl 'bold' etc) use ttNMResult.uNameID == 1 // see http://www.microsoft.com/OpenType/OTSpec/name.htm if (ttNMResult.uNameID == 4) { long fPos = fs.Position; fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset; char[] szResult = r.ReadChars(ttNMResult.uStringLength); if (szResult.Length != 0) { // some fonts are \0 A \0 r \0 i \0 a \0 l.... UTf8 encoding doesn't help if (szResult[0] == '\0') { int count = 0; char[] temp = new char[szResult.Length / 2]; for (int j = 1; j < szResult.Length; j += 2) { temp[count++] = szResult[j]; } szResult = temp; } result = new String(szResult); break; } } } } } finally { r.Close(); if (fs != null) { fs.Dispose(); } } return(result); }