Exemple #1
0
        /// <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);
        }
Exemple #2
0
        public static CompactFontFormatIndex ReadDictionaryData(CompactFontFormatData data)
        {
            var index = ReadIndex(data);

            if (index.Length == 0)
            {
                return(new CompactFontFormatIndex(null));
            }

            var count = index.Length - 1;

            var results = new byte[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}.");
                }

                if (length > data.Length)
                {
                    throw new InvalidOperationException($"Attempted to read data of length {length} in data array of length {data.Length}.");
                }

                results[i] = data.ReadBytes(length);
            }

            return(new CompactFontFormatIndex(results));
        }
        private static CompactFontFormatFormat1Encoding ReadFormat1Encoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList <string> stringIndex, byte format)
        {
            var numberOfRanges = data.ReadCard8();

            var fromRanges = new List <(int code, int sid, string str)>();

            var gid = 1;

            for (var i = 0; i < numberOfRanges; i++)
            {
                int rangeFirst = data.ReadCard8();
                int rangeLeft  = data.ReadCard8();
                for (var j = 0; j < 1 + rangeLeft; j++)
                {
                    var sid  = charset.GetStringIdByGlyphId(gid);
                    var code = rangeFirst + j;
                    var str  = ReadString(sid, stringIndex);
                    fromRanges.Add((code, sid, str));
                    gid++;
                }
            }

            IReadOnlyList <CompactFontFormatBuiltInEncoding.Supplement> supplements = new List <CompactFontFormatBuiltInEncoding.Supplement>();

            if (HasSupplement(format))
            {
                supplements = ReadSupplement(data, stringIndex);
            }

            return(new CompactFontFormatFormat1Encoding(numberOfRanges, fromRanges, supplements));
        }
        public static Encoding ReadEncoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList <string> stringIndex)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            var format = data.ReadCard8();

            // A few fonts have multiply encoded glyphs which are indicated by setting the high order bit of the format byte.
            // To get the real format out & with 0111 1111 (0x7f).
            var baseFormat = format & 0x7f;

            switch (baseFormat)
            {
            case 0:
                return(ReadFormat0Encoding(data, charset, stringIndex, format));

            case 1:
                return(ReadFormat1Encoding(data, charset, stringIndex, format));

            default:
                throw new InvalidFontFormatException($"The provided format {format} for this Compact Font Format encoding was invalid.");
            }
        }
        public void Parse(CompactFontFormatData data, string name, byte[] topDictionaryIndex, string[] stringIndex)
        {
            var individualData = new CompactFontFormatData(topDictionaryIndex);

            var dictionary = topLevelDictionaryReader.Read(individualData, stringIndex);

            var privateDictionary = new CompactFontFormatPrivateDictionary();

            if (dictionary.PrivateDictionarySizeAndOffset.Item2 >= 0)
            {
                data.Seek(dictionary.PrivateDictionarySizeAndOffset.Item2);

                privateDictionary = privateDictionaryReader.Read(data, stringIndex);
            }

            if (dictionary.CharSetOffset >= 0)
            {
            }

            if (dictionary.CharStringsOffset >= 0)
            {
                data.Seek(dictionary.CharStringsOffset);

                var index = indexReader.ReadDictionaryData(data);
            }
        }
        private static CompactFontFormatHeader ReadHeader(CompactFontFormatData data)
        {
            var major      = data.ReadCard8();
            var minor      = data.ReadCard8();
            var headerSize = data.ReadCard8();
            var offsetSize = data.ReadOffsize();

            return(new CompactFontFormatHeader(major, minor, headerSize, offsetSize));
        }
        private static ICompactFontFormatCharset ReadCharset(CompactFontFormatData data, CompactFontFormatTopLevelDictionary topDictionary,
                                                             CompactFontFormatIndex charStringIndex, IReadOnlyList <string> stringIndex)
        {
            data.Seek(topDictionary.CharSetOffset);

            var format = data.ReadCard8();

            switch (format)
            {
            case 0:
            {
                var glyphToNamesAndStringId = new List <(int glyphId, int stringId, string name)>();

                for (var glyphId = 1; glyphId < charStringIndex.Count; glyphId++)
                {
                    var stringId = data.ReadSid();
                    glyphToNamesAndStringId.Add((glyphId, stringId, ReadString(stringId, stringIndex)));
                }

                return(new CompactFontFormatFormat0Charset(glyphToNamesAndStringId));
            }

            case 1:
            case 2:
            {
                var glyphToNamesAndStringId = new List <(int glyphId, int stringId, string name)>();

                for (var glyphId = 1; glyphId < charStringIndex.Count; glyphId++)
                {
                    var firstSid      = data.ReadSid();
                    var numberInRange = format == 1 ? data.ReadCard8() : data.ReadCard16();

                    glyphToNamesAndStringId.Add((glyphId, firstSid, ReadString(firstSid, stringIndex)));
                    for (var i = 0; i < numberInRange; i++)
                    {
                        glyphId++;
                        var sid = firstSid + i + 1;
                        glyphToNamesAndStringId.Add((glyphId, sid, ReadString(sid, stringIndex)));
                    }
                }

                if (format == 1)
                {
                    return(new CompactFontFormatFormat1Charset(glyphToNamesAndStringId));
                }

                return(new CompactFontFormatFormat2Charset(glyphToNamesAndStringId));
            }

            default:
                throw new InvalidOperationException($"Unrecognized format for the Charset table in a CFF font. Got: {format}.");
            }
        }
        private static CompactFontFormat0FdSelect ReadFormat0FdSelect(CompactFontFormatData data, int numberOfGlyphs,
                                                                      RegistryOrderingSupplement registryOrderingSupplement)
        {
            var dictionaries = new int[numberOfGlyphs];

            for (var i = 0; i < numberOfGlyphs; i++)
            {
                dictionaries[i] = data.ReadCard8();
            }

            return(new CompactFontFormat0FdSelect(registryOrderingSupplement, dictionaries));
        }
        public int[] ReadIndex(CompactFontFormatData data)
        {
            var count = data.ReadCard16();

            var offsetSize = data.ReadOffsize();

            var offsets = new int[count + 1];

            for (var i = 0; i < offsets.Length; i++)
            {
                offsets[i] = data.ReadOffset(offsetSize);
            }

            return(offsets);
        }
        private static CompactFontFormat3FdSelect ReadFormat3FdSelect(CompactFontFormatData data, RegistryOrderingSupplement registryOrderingSupplement)
        {
            var numberOfRanges = data.ReadCard16();
            var ranges         = new CompactFontFormat3FdSelect.Range3[numberOfRanges];

            for (var i = 0; i < numberOfRanges; i++)
            {
                var first      = data.ReadCard16();
                var dictionary = data.ReadCard8();

                ranges[i] = new CompactFontFormat3FdSelect.Range3(first, dictionary);
            }

            var sentinel = data.ReadCard16();

            return(new CompactFontFormat3FdSelect(registryOrderingSupplement, ranges, sentinel));
        }
        /// <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));
        }
        private static Type2CharStrings ReadCharStrings(CompactFontFormatData data, CompactFontFormatTopLevelDictionary topDictionary,
                                                        CompactFontFormatIndex charStringIndex,
                                                        CompactFontFormatSubroutinesSelector subroutinesSelector,
                                                        ICompactFontFormatCharset charset)
        {
            data.Seek(topDictionary.CharStringsOffset);

            switch (topDictionary.CharStringType)
            {
            case CompactFontFormatCharStringType.Type1:
                throw new NotImplementedException("Type 1 CharStrings are not currently supported in CFF font.");

            case CompactFontFormatCharStringType.Type2:
                return(Type2CharStringParser.Parse(charStringIndex, subroutinesSelector, charset));

            default:
                throw new ArgumentOutOfRangeException($"Unexpected CharString type in CFF font: {topDictionary.CharStringType}.");
            }
        }
Exemple #13
0
        public static int[] ReadIndex(CompactFontFormatData data)
        {
            var count = data.ReadCard16();

            if (count == 0)
            {
                return(EmptyArray <int> .Instance);
            }

            var offsetSize = data.ReadOffsize();

            var offsets = new int[count + 1];

            for (var i = 0; i < offsets.Length; i++)
            {
                offsets[i] = data.ReadOffset(offsetSize);
            }

            return(offsets);
        }
        public byte[][] ReadDictionaryData(CompactFontFormatData data)
        {
            var index = ReadIndex(data);

            var count = index.Length - 1;

            var results = new byte[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}.");
                }

                results[i] = data.ReadBytes(length);
            }

            return(results);
        }
        private static CompactFontFormatFormat0Encoding ReadFormat0Encoding(CompactFontFormatData data, ICompactFontFormatCharset charset, IReadOnlyList <string> stringIndex, byte format)
        {
            var numberOfCodes = data.ReadCard8();

            var values = new List <(int code, int sid, string str)>();

            for (var i = 1; i <= numberOfCodes; i++)
            {
                var code = data.ReadCard8();
                var sid  = charset.GetStringIdByGlyphId(i);
                var str  = ReadString(sid, stringIndex);
                values.Add((code, sid, str));
            }

            IReadOnlyList <CompactFontFormatBuiltInEncoding.Supplement> supplements = new List <CompactFontFormatBuiltInEncoding.Supplement>();

            if (HasSupplement(format))
            {
                supplements = ReadSupplement(data, stringIndex);
            }

            return(new CompactFontFormatFormat0Encoding(values, supplements));
        }
        public void Parse(CompactFontFormatData data)
        {
            var tag = ReadTag(data);

            switch (tag)
            {
            case TagOtto:
                throw new NotImplementedException("Currently tagged CFF data is not supported.");

            case TagTtcf:
                throw new NotSupportedException("True Type Collection fonts are not supported.");

            case TagTtfonly:
                throw new NotSupportedException("OpenType fonts containing a true type font are not supported.");

            default:
                data.Seek(0);
                break;
            }

            var header = ReadHeader(data);

            var fontNames = ReadStringIndex(data);

            var topLevelDict = indexReader.ReadDictionaryData(data);

            var stringIndex = ReadStringIndex(data);

            var globalSubroutineIndex = indexReader.ReadDictionaryData(data);

            for (var i = 0; i < fontNames.Length; i++)
            {
                var fontName = fontNames[i];

                individualFontParser.Parse(data, fontName, topLevelDict[i], stringIndex);
            }
        }
        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));
        }
        private static IReadOnlyList <CompactFontFormatBuiltInEncoding.Supplement> ReadSupplement(CompactFontFormatData dataInput,
                                                                                                  IReadOnlyList <string> stringIndex)
        {
            var numberOfSupplements = dataInput.ReadCard8();
            var supplements         = new CompactFontFormatBuiltInEncoding.Supplement[numberOfSupplements];

            for (var i = 0; i < supplements.Length; i++)
            {
                var code = dataInput.ReadCard8();
                var sid  = dataInput.ReadSid();
                var name = ReadString(sid, stringIndex);
                supplements[i] = new CompactFontFormatBuiltInEncoding.Supplement(code, sid, name);
            }

            return(supplements);
        }
Exemple #20
0
        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)
            {
                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 = indexReader.ReadDictionaryData(data);
            }

            data.Seek(topDictionary.CharStringsOffset);

            var charStringIndex = indexReader.ReadDictionaryData(data);

            ICompactFontFormatCharset charset = null;

            if (topDictionary.IsCidFont && topDictionary.CharSetOffset >= 0 && topDictionary.CharSetOffset <= 2)
            {
                switch (topDictionary.CharSetOffset)
                {
                case 0:
                    charset = CompactFontFormatIsoAdobeCharset.Value;
                    break;

                case 1:
                    charset = CompactFontFormatExpertCharset.Value;
                    break;

                case 2:
                    charset = CompactFontFormatExpertSubsetCharset.Value;
                    break;
                }
            }
            else
            {
                data.Seek(topDictionary.CharSetOffset);

                var format = data.ReadCard8();

                switch (format)
                {
                case 0:
                {
                    var glyphToNamesAndStringId = new List <(int glyphId, int stringId, string name)>();

                    for (var glyphId = 1; glyphId < charStringIndex.Count; glyphId++)
                    {
                        var stringId = data.ReadSid();
                        glyphToNamesAndStringId.Add((glyphId, stringId, ReadString(stringId, stringIndex)));
                    }

                    charset = new CompactFontFormatFormat0Charset(glyphToNamesAndStringId);

                    break;
                }

                case 1:
                case 2:
                {
                    var glyphToNamesAndStringId = new List <(int glyphId, int stringId, string name)>();

                    for (var glyphId = 1; glyphId < charStringIndex.Count; glyphId++)
                    {
                        var firstSid      = data.ReadSid();
                        var numberInRange = format == 1 ? data.ReadCard8() : data.ReadCard16();

                        glyphToNamesAndStringId.Add((glyphId, firstSid, ReadString(firstSid, stringIndex)));
                        for (var i = 0; i < numberInRange; i++)
                        {
                            glyphId++;
                            var sid = firstSid + i + 1;
                            glyphToNamesAndStringId.Add((glyphId, sid, ReadString(sid, stringIndex)));
                        }
                    }

                    if (format == 1)
                    {
                        charset = new CompactFontFormatFormat1Charset(glyphToNamesAndStringId);
                    }
                    else
                    {
                        charset = new CompactFontFormatFormat2Charset(glyphToNamesAndStringId);
                    }

                    break;
                }

                default:
                    throw new InvalidOperationException($"Unrecognized format for the Charset table in a CFF font. Got: {format}.");
                }
            }

            data.Seek(topDictionary.CharStringsOffset);

            Type2CharStrings charStrings;

            switch (topDictionary.CharStringType)
            {
            case CompactFontFormatCharStringType.Type1:
                throw new NotImplementedException();

            case CompactFontFormatCharStringType.Type2:
                charStrings = Type2CharStringParser.Parse(charStringIndex, localSubroutines, globalSubroutineIndex, charset);
                break;

            default:
                throw new ArgumentOutOfRangeException($"Unexpected CharString type in CFF font: {topDictionary.CharStringType}.");
            }

            return(new CompactFontFormatFont(topDictionary, privateDictionary, charset, Union <Type1CharStrings, Type2CharStrings> .Two(charStrings)));
        }
        private static string ReadTag(CompactFontFormatData data)
        {
            var tag = data.ReadString(4, OtherEncodings.Iso88591);

            return(tag);
        }