public static FsType GetFsType(string fontFullName) { if (!File.Exists(fontFullName)) { throw new FileNotFoundException(fontFullName); } FileStream fs = new FileStream(fontFullName, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); TT_OFFSET_TABLE ttResult = GetOffsetTable(r); //ttf Must be maj =1 minor = 0 int numTables = 0; if (ttResult.uMajorVersion == 1 && ttResult.uMinorVersion == 0) { numTables = ttResult.uNumOfTables; } else { fs.Position = 0L; SFNT sFnt = GetSfnt(r); string szSfnt = string.Format("{0}{1}{2}{3}", (char)sFnt.szSfnt1, (char)sFnt.szSfnt2, (char)sFnt.szSfnt3, (char)sFnt.szSfnt4); switch (szSfnt) { case "OTTO": OT_OFFSET_TABLE otResult = GetOpenTypeOffsetTable(r); numTables = otResult.uNumOfTables; break; case "ttcf": TTC_HEADER_1 ttcHeader = GetTtcHeader(r); if ((ttcHeader.uMajorVersion != 1 && ttcHeader.uMajorVersion != 2) || ttcHeader.uMinorVersion != 0) { throw new VersionNotFoundException(fontFullName + " Expected header version 1.0 or 2.0"); } GetTtcOffsets(r, ttcHeader.uNumFonts); fs.Position = long.Parse(ttcOffsets[0].ToString()); ttResult = GetOffsetTable(r); if (ttResult.uMajorVersion == 1 && ttResult.uMinorVersion == 0) { numTables = ttResult.uNumOfTables; } else { throw new VersionNotFoundException(fontFullName + " expected TrueType version 1.0"); } break; default: throw new MissingFieldException(fontFullName + " Font type should be ttcf or OTTO"); } } bool bFound = false; TT_TABLE_DIRECTORY tbName = new TT_TABLE_DIRECTORY(); for (int i = 0; i < numTables; i++) { tbName = GetNameTable(r); string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString(); if (szName != null) { if (szName == "OS/2") // http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=IWS-AppendixC { bFound = true; tbName.uLength = BigEndianValue(tbName.uLength); tbName.uOffset = BigEndianValue(tbName.uOffset); break; } } } if (bFound) { fs.Position = tbName.uOffset; TT_OS2_RECORD ttOs2Result = GetOs2Record(r); return(ttOs2Result.fsType); } throw new MissingFieldException(fontFullName + " should contain OS/2 table"); }
public static string GetPostscriptName(string fontFullName) { if (!File.Exists(fontFullName)) { return(string.Empty); } FileStream fs = new FileStream(fontFullName, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); TT_OFFSET_TABLE ttResult = GetOffsetTable(r); //ttf Must be maj =1 minor = 0 int numTables = 0; if (ttResult.uMajorVersion == 1 && ttResult.uMinorVersion == 0) { numTables = ttResult.uNumOfTables; } else { fs.Position = 0L; SFNT sFnt = GetSfnt(r); string szSfnt = string.Format("{0}{1}{2}{3}", (char)sFnt.szSfnt1, (char)sFnt.szSfnt2, (char)sFnt.szSfnt3, (char)sFnt.szSfnt4); switch (szSfnt) { case "OTTO": OT_OFFSET_TABLE otResult = GetOpenTypeOffsetTable(r); numTables = otResult.uNumOfTables; break; case "ttcf": TTC_HEADER_1 ttcHeader = GetTtcHeader(r); if ((ttcHeader.uMajorVersion != 1 && ttcHeader.uMajorVersion != 2) || ttcHeader.uMinorVersion != 0) { return(string.Empty); } GetTtcOffsets(r, ttcHeader.uNumFonts); fs.Position = long.Parse(ttcOffsets[0].ToString()); ttResult = GetOffsetTable(r); if (ttResult.uMajorVersion == 1 && ttResult.uMinorVersion == 0) { numTables = ttResult.uNumOfTables; } else { return(string.Empty); } break; default: return(string.Empty); } } bool bFound = false; TT_TABLE_DIRECTORY tbName = new TT_TABLE_DIRECTORY(); for (int i = 0; i < numTables; i++) { tbName = GetNameTable(r); string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString(); if (szName != null) { if (szName == "name") { bFound = true; tbName.uLength = BigEndianValue(tbName.uLength); tbName.uOffset = BigEndianValue(tbName.uOffset); break; } } } if (bFound) { fs.Position = tbName.uOffset; TT_NAME_TABLE_HEADER ttNTResult = GetNameTableHeader(r); for (int i = 0; i < ttNTResult.uNRCount; i++) { TT_NAME_RECORD ttNMResult = GetNameRecord(r); const int PostscriptNameId = 6; if (ttNMResult.uNameID == PostscriptNameId) { fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset; char[] szResult = r.ReadChars(ttNMResult.uStringLength); string result = ""; // Usually the uEncodingID will tell us whether we're using single or double-byte encoding, // but sometimes it lies. Verify by testing the first character in the array for '\0' int uId = ttNMResult.uEncodingID; if (szResult[0] == '\0') { uId = 3; } for (int j = 0; j < ttNMResult.uStringLength; j++) { switch (uId) { case 0: // SIL Fonts use this encoding result += szResult[j]; break; case 3: // Windows Fonts use this encoding (first byte is NUL) j++; if (j < ttNMResult.uStringLength) { result += szResult[j]; } break; } } return(result); } } } return(string.Empty); }
private static SFNT GetSfnt(BinaryReader r) { byte[] buff = r.ReadBytes(Marshal.SizeOf(sFnt)); IntPtr ptr = Marshal.AllocHGlobal(buff.Length); Marshal.Copy(buff, 0x0, ptr, buff.Length); sFnt = (SFNT)Marshal.PtrToStructure(ptr, typeof(SFNT)); Marshal.FreeHGlobal(ptr); return sFnt; }