private static TypographicFont ParseOpenTypeStream(BigEndianBinaryReader br, long streamOffset, string filename) { br.BaseStream.Seek(streamOffset, SeekOrigin.Begin); // This version check is crucial, since there is no tag at the beginning of the stream. // If it doesn't match either of the known spec version IDs, it's probably a FON file which we don't parse. var version = br.ReadUInt32(); const uint trueTypeOutlinesVersion = 0x00010000; const uint ccfVersion = 0x4F54544F; // "OTTO" if (version != trueTypeOutlinesVersion && version != ccfVersion) { return(null); } var numTables = br.ReadUInt16(); var searchRange = br.ReadUInt16(); var entrySelector = br.ReadUInt16(); var rangeShift = br.ReadUInt16(); var familyNames = default(FamilyNamesInfo?); var os2Info = default(OS2Info?); for (var ti = 0; ti < numTables; ti++) { var tag = Encoding.ASCII.GetString(br.ReadBytes(4)); var checksum = br.ReadUInt32(); var offset = br.ReadUInt32(); var length = br.ReadUInt32(); var position = br.BaseStream.Position; switch (tag) { case "name": familyNames = ReadFamilyNames(br, offset); break; case "OS/2": os2Info = ReadOS2(br, offset); break; } if (familyNames != null && os2Info != null) { break; } br.BaseStream.Seek(position, SeekOrigin.Begin); } if (familyNames == null || os2Info == null) { return(null); } return(new TypographicFont(familyNames.Value, os2Info.Value, filename)); }
public static TypographicFont[] Read(string filename) { // Do not check the file extension. Files are often misnamed. Detect by contents. using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read)) using (var br = new BigEndianBinaryReader(file)) { if (Encoding.ASCII.GetString(br.ReadBytes(4)) == "ttcf") { // Font collection detected. // This check is probably not necessary, since future versions are probably going to be back-compatible var version = br.ReadUInt32(); // const uint knownVersion1 = 0x00010000, knownVersion2 = 0x00020000; // if (version != knownVersion1 && version != knownVersion2) return new TypographicFont[0]; var numContainedFonts = br.ReadUInt32(); var fontStreamOffsets = new uint[numContainedFonts]; for (var fi = 0; fi < fontStreamOffsets.Length; fi++) { fontStreamOffsets[fi] = br.ReadUInt32(); } var r = new List <TypographicFont>(); for (var fi = 0; fi < fontStreamOffsets.Length; fi++) { var font = ParseOpenTypeStream(br, fontStreamOffsets[fi], filename); if (font != null) { r.Add(font); } } return(r.ToArray()); } else { // No collection detected, assume this is an OpenType stream. var font = ParseOpenTypeStream(br, 0, filename); return(font == null ? new TypographicFont[0] : new[] { font }); } } }