/// <summary> /// Reads indexed string data. /// </summary> private static string[] ReadStringIndex(CompactFontFormatData data) { var index = CompactFontFormatIndexReader.ReadIndex(data); if (index.Length == 0) { return(EmptyArray <string> .Instance); } var count = index.Length - 1; var result = new string[count]; for (var i = 0; i < count; i++) { var length = index[i + 1] - index[i]; if (length < 0) { throw new InvalidOperationException($"Negative object length {length} at {i}. Current position: {data.Position}."); } result[i] = data.ReadString(length, OtherEncodings.Iso88591); } return(result); }
public CompactFontFormatIndividualFontParser(CompactFontFormatIndexReader indexReader, CompactFontFormatTopLevelDictionaryReader topLevelDictionaryReader, CompactFontFormatPrivateDictionaryReader privateDictionaryReader) { this.indexReader = indexReader; this.topLevelDictionaryReader = topLevelDictionaryReader; this.privateDictionaryReader = privateDictionaryReader; }
/// <summary> /// Read the Compact Font Format font from the input data. /// </summary> public static CompactFontFormatFontCollection Parse(CompactFontFormatData data) { var tag = ReadTag(data); switch (tag) { // An OpenType font containing CFF data. case TagOtto: throw new NotSupportedException("Currently tagged CFF data is not supported."); case TagTtcf: throw new NotSupportedException("True Type Collection fonts are not currently supported."); case TagTtfonly: throw new NotSupportedException("OpenType fonts containing a true type font are not currently supported."); default: data.Seek(0); break; } var header = ReadHeader(data); var fontNames = ReadStringIndex(data); var topLevelDictionaryIndex = CompactFontFormatIndexReader.ReadDictionaryData(data); var stringIndex = ReadStringIndex(data); var globalSubroutineIndex = CompactFontFormatIndexReader.ReadDictionaryData(data); var fonts = new Dictionary <string, CompactFontFormatFont>(); var individualFontParser = new CompactFontFormatIndividualFontParser(new CompactFontFormatTopLevelDictionaryReader(), new CompactFontFormatPrivateDictionaryReader()); for (var i = 0; i < fontNames.Length; i++) { var fontName = fontNames[i]; fonts[fontName] = individualFontParser.Parse(data, fontName, topLevelDictionaryIndex[i], stringIndex, globalSubroutineIndex); } return(new CompactFontFormatFontCollection(header, fonts)); }
public CompactFontFormatFont Parse(CompactFontFormatData data, string name, IReadOnlyList <byte> topDictionaryIndex, IReadOnlyList <string> stringIndex, CompactFontFormatIndex globalSubroutineIndex) { var individualData = new CompactFontFormatData(topDictionaryIndex.ToArray()); var topDictionary = topLevelDictionaryReader.Read(individualData, stringIndex); var privateDictionary = CompactFontFormatPrivateDictionary.GetDefault(); if (topDictionary.PrivateDictionaryLocation.HasValue && topDictionary.PrivateDictionaryLocation.Value.Size > 0) { var privateDictionaryBytes = data.SnapshotPortion(topDictionary.PrivateDictionaryLocation.Value.Offset, topDictionary.PrivateDictionaryLocation.Value.Size); privateDictionary = privateDictionaryReader.Read(privateDictionaryBytes, stringIndex); } if (topDictionary.CharStringsOffset < 0) { throw new InvalidOperationException("Expected CFF to contain a CharString offset."); } var localSubroutines = CompactFontFormatIndex.None; if (privateDictionary.LocalSubroutineOffset.HasValue && topDictionary.PrivateDictionaryLocation.HasValue) { data.Seek(privateDictionary.LocalSubroutineOffset.Value + topDictionary.PrivateDictionaryLocation.Value.Offset); localSubroutines = CompactFontFormatIndexReader.ReadDictionaryData(data); } data.Seek(topDictionary.CharStringsOffset); var charStringIndex = CompactFontFormatIndexReader.ReadDictionaryData(data); ICompactFontFormatCharset charset; if (topDictionary.CharSetOffset >= 0) { var charsetId = topDictionary.CharSetOffset; if (!topDictionary.IsCidFont && charsetId == 0) { charset = CompactFontFormatIsoAdobeCharset.Value; } else if (!topDictionary.IsCidFont && charsetId == 1) { charset = CompactFontFormatExpertCharset.Value; } else if (!topDictionary.IsCidFont && charsetId == 2) { charset = CompactFontFormatExpertSubsetCharset.Value; } else { charset = ReadCharset(data, topDictionary, charStringIndex, stringIndex); } } else { if (topDictionary.IsCidFont) { // a CID font with no charset does not default to any predefined charset charset = new CompactFontFormatEmptyCharset(charStringIndex.Count); } else { charset = CompactFontFormatIsoAdobeCharset.Value; } } if (topDictionary.IsCidFont) { return(ReadCidFont(data, topDictionary, charStringIndex.Count, stringIndex, privateDictionary, charset, globalSubroutineIndex, localSubroutines, charStringIndex)); } var encoding = topDictionary.EncodingOffset; Encoding fontEncoding = null; if (encoding != CompactFontFormatTopLevelDictionary.UnsetOffset) { if (encoding == 0) { fontEncoding = CompactFontFormatStandardEncoding.Instance; } else if (encoding == 1) { fontEncoding = CompactFontFormatExpertEncoding.Instance; } else { data.Seek(encoding); fontEncoding = CompactFontFormatEncodingReader.ReadEncoding(data, charset, stringIndex); } } var subroutineSelector = new CompactFontFormatSubroutinesSelector(globalSubroutineIndex, localSubroutines); var charStrings = ReadCharStrings(data, topDictionary, charStringIndex, subroutineSelector, charset); return(new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union <Type1CharStrings, Type2CharStrings> .Two(charStrings), fontEncoding)); }
private CompactFontFormatCidFont ReadCidFont(CompactFontFormatData data, CompactFontFormatTopLevelDictionary topLevelDictionary, int numberOfGlyphs, IReadOnlyList <string> stringIndex, CompactFontFormatPrivateDictionary privateDictionary, ICompactFontFormatCharset charset, CompactFontFormatIndex globalSubroutines, CompactFontFormatIndex localSubroutinesTop, CompactFontFormatIndex charStringIndex) { var offset = topLevelDictionary.CidFontOperators.FontDictionaryArray; data.Seek(offset); var fontDict = CompactFontFormatIndexReader.ReadDictionaryData(data); var privateDictionaries = new List <CompactFontFormatPrivateDictionary>(); var fontDictionaries = new List <CompactFontFormatTopLevelDictionary>(); var fontLocalSubroutines = new List <CompactFontFormatIndex>(); foreach (var index in fontDict) { var topLevelDictionaryCid = topLevelDictionaryReader.Read(new CompactFontFormatData(index), stringIndex); if (!topLevelDictionaryCid.PrivateDictionaryLocation.HasValue) { throw new InvalidFontFormatException("The CID keyed Compact Font Format font did not contain a private dictionary for the font dictionary."); } var privateDictionaryBytes = data.SnapshotPortion(topLevelDictionaryCid.PrivateDictionaryLocation.Value.Offset, topLevelDictionaryCid.PrivateDictionaryLocation.Value.Size); var privateDictionaryCid = privateDictionaryReader.Read(privateDictionaryBytes, stringIndex); // CFFParser.java line 625 - read the local subroutines. if (privateDictionaryCid.LocalSubroutineOffset.HasValue && privateDictionaryCid.LocalSubroutineOffset.Value > 0) { data.Seek(topLevelDictionaryCid.PrivateDictionaryLocation.Value.Offset + privateDictionaryCid.LocalSubroutineOffset.Value); var localSubroutines = CompactFontFormatIndexReader.ReadDictionaryData(data); fontLocalSubroutines.Add(localSubroutines); } else { fontLocalSubroutines.Add(null); } fontDictionaries.Add(topLevelDictionaryCid); privateDictionaries.Add(privateDictionaryCid); } data.Seek(topLevelDictionary.CidFontOperators.FontDictionarySelect); var format = data.ReadCard8(); ICompactFontFormatFdSelect fdSelect; switch (format) { case 0: { fdSelect = ReadFormat0FdSelect(data, numberOfGlyphs, topLevelDictionary.CidFontOperators.Ros); break; } case 3: { fdSelect = ReadFormat3FdSelect(data, topLevelDictionary.CidFontOperators.Ros); break; } default: throw new InvalidFontFormatException($"Invalid Font Dictionary Select format: {format}."); } var subroutineSelector = new CompactFontFormatSubroutinesSelector(globalSubroutines, localSubroutinesTop, fdSelect, fontLocalSubroutines); var charStrings = ReadCharStrings(data, topLevelDictionary, charStringIndex, subroutineSelector, charset); var union = Union <Type1CharStrings, Type2CharStrings> .Two(charStrings); return(new CompactFontFormatCidFont(topLevelDictionary, privateDictionary, charset, union, fontDictionaries, privateDictionaries, fdSelect)); }
public CompactFontFormatParser(CompactFontFormatIndividualFontParser individualFontParser, CompactFontFormatIndexReader indexReader) { this.individualFontParser = individualFontParser; this.indexReader = indexReader; }