示例#1
0
        public void Parse(NumericToken numeric, ITokenScanner tokenScanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            /*
             * For example:
             * 3 begincodespacerange
             *  <00>    <80>
             *  <8140>  <9ffc>
             *  <a0>    <de>
             * endcodespacerange
             */

            var ranges = new List <CodespaceRange>(numeric.Int);

            for (var i = 0; i < numeric.Int; i++)
            {
                if (!tokenScanner.MoveNext() || !(tokenScanner.CurrentToken is HexToken start))
                {
                    throw new InvalidOperationException("Codespace range contains an unexpected token: " + tokenScanner.CurrentToken);
                }

                if (!tokenScanner.MoveNext() || !(tokenScanner.CurrentToken is HexToken end))
                {
                    throw new InvalidOperationException("Codespace range contains an unexpected token: " + tokenScanner.CurrentToken);
                }

                ranges.Add(new CodespaceRange(start.Bytes, end.Bytes));
            }

            builder.CodespaceRanges = ranges;
        }
        public void Parse(NumericToken numeric, ITokenScanner tokenScanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            for (var i = 0; i < numeric.Int; i++)
            {
                if (!tokenScanner.MoveNext() || !(tokenScanner.CurrentToken is HexToken inputCode))
                {
                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }

                if (!tokenScanner.MoveNext())
                {
                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }

                if (tokenScanner.CurrentToken is NameToken characterName)
                {
                    builder.AddBaseFontCharacter(inputCode.Bytes, characterName.Data);
                }
                else if (tokenScanner.CurrentToken is HexToken characterCode)
                {
                    builder.AddBaseFontCharacter(inputCode.Bytes, characterCode.Bytes);
                }
                else
                {
                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }
            }
        }
示例#3
0
        public void Parse(NumericToken numeric, ITokenScanner scanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            for (var i = 0; i < numeric.Int; i++)
            {
                if (!scanner.TryReadToken(out HexToken startHexToken))
                {
                    throw new InvalidFontFormatException("Could not find the starting hex token for the CIDRange in this font.");
                }

                if (!scanner.TryReadToken(out HexToken endHexToken))
                {
                    throw new InvalidFontFormatException("Could not find the end hex token for the CIDRange in this font.");
                }

                if (!scanner.TryReadToken(out NumericToken mappedCode))
                {
                    throw new InvalidFontFormatException("Could not find the starting CID numeric token for the CIDRange in this font.");
                }

                var start = HexToken.ConvertHexBytesToInt(startHexToken);
                var end   = HexToken.ConvertHexBytesToInt(endHexToken);

                var range = new CidRange(start, end, mappedCode.Int);

                builder.AddCidRange(range);
            }
        }
示例#4
0
        public CMap Parse(IInputBytes inputBytes)
        {
            var scanner = new CoreTokenScanner(inputBytes);

            var builder = new CharacterMapBuilder();

            IToken previousToken = null;

            while (scanner.MoveNext())
            {
                var token = scanner.CurrentToken;

                if (token is OperatorToken operatorToken)
                {
                    switch (operatorToken.Data)
                    {
                    case "usecmap":
                    {
                        if (previousToken is NameToken name && TryParseExternal(name.Data, out var external))
                        {
                            builder.UseCMap(external);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding external cmap call: " + previousToken);
                        }
                        break;
                    }
示例#5
0
        public void Parse(NumericToken numeric, ITokenScanner tokenScanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            for (var i = 0; i < numeric.Int; i++)
            {
                if (!tokenScanner.MoveNext() || !(tokenScanner.CurrentToken is HexToken inputCode))
                {
                    if (tokenScanner.CurrentToken is OperatorToken op &&
                        (string.Equals(op.Data, "endbfchar", StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(op.Data, "endcmap", StringComparison.OrdinalIgnoreCase)))
                    {
                        return;
                    }

                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }

                if (!tokenScanner.MoveNext())
                {
                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }

                if (tokenScanner.CurrentToken is NameToken characterName)
                {
                    builder.AddBaseFontCharacter(inputCode.Bytes, characterName.Data);
                }
                else if (tokenScanner.CurrentToken is HexToken characterCode)
                {
                    builder.AddBaseFontCharacter(inputCode.Bytes, characterCode.Bytes);
                }
                else
                {
                    throw new InvalidOperationException($"Base font characters definition contains invalid item at index {i}: {tokenScanner.CurrentToken}");
                }
            }
        }
示例#6
0
        public void CanParseWithHex()
        {
            var input = StringBytesTestConverter.Scanner("<8141> <8147> <8141>");

            var builder = new CharacterMapBuilder();

            parser.Parse(new NumericToken(1), input, builder, false);

            Assert.Equal(7, builder.BaseFontCharacterMap.Count);

            Assert.Equal("腁", builder.BaseFontCharacterMap[33089]);
            Assert.Equal(char.ConvertFromUtf32(33090), builder.BaseFontCharacterMap[33090]);
        }
示例#7
0
        public void CanParseWithArray()
        {
            var input = StringBytesTestConverter.Scanner("<0003> <0004> [<0020> <0041>]");

            var builder = new CharacterMapBuilder();

            parser.Parse(new NumericToken(1), input, builder, false);

            Assert.Equal(2, builder.BaseFontCharacterMap.Count);

            Assert.Equal(" ", builder.BaseFontCharacterMap[3]);
            Assert.Equal("A", builder.BaseFontCharacterMap[4]);
        }
示例#8
0
        public void CanParseTwoRowsWithDifferentFormat()
        {
            var input = StringBytesTestConverter.Scanner(@"<0019> <001B> <3C>
<0001> <0003> [/happy /feet /penguin]");

            var builder = new CharacterMapBuilder();

            parser.Parse(new NumericToken(2), input, builder, false);

            Assert.Equal(6, builder.BaseFontCharacterMap.Count);

            Assert.Equal("happy", builder.BaseFontCharacterMap[1]);
            Assert.Equal("feet", builder.BaseFontCharacterMap[2]);
            Assert.Equal("penguin", builder.BaseFontCharacterMap[3]);

            Assert.Equal("<", builder.BaseFontCharacterMap[25]);
        }
示例#9
0
        public void Parse(NumericToken numeric, ITokenScanner tokenScanner, CharacterMapBuilder builder)
        {
            /*
             * For example:
             * 3 begincodespacerange
             *  <00>    <80>
             *  <8140>  <9ffc>
             *  <a0>    <de>
             * endcodespacerange
             */

            var ranges = new List <CodespaceRange>(numeric.Int);

            for (var i = 0; i < numeric.Int; i++)
            {
                if (!tokenScanner.MoveNext())
                {
                    throw new InvalidOperationException("Codespace range have reach an unexpected end");
                }

                if (tokenScanner.CurrentToken is OperatorToken operatorToken && operatorToken.Data == "endcodespacerange")
                {
                    // Don't add this code space range
                    break;
                }

                if (!(tokenScanner.CurrentToken is HexToken start))
                {
                    throw new InvalidOperationException("Codespace range contains an unexpected token: " + tokenScanner.CurrentToken);
                }

                if (!tokenScanner.MoveNext() || !(tokenScanner.CurrentToken is HexToken end))
                {
                    throw new InvalidOperationException("Codespace range contains an unexpected token: " + tokenScanner.CurrentToken);
                }

                ranges.Add(new CodespaceRange(start.Bytes, end.Bytes));
            }

            builder.CodespaceRanges = ranges;
        }
示例#10
0
        public void ColorspaceParserError()
        {
            var parser         = new CodespaceRangeParser();
            var byteArrayInput = new ByteArrayInputBytes(OtherEncodings.StringAsLatin1Bytes("1 begincodespacerange\nendcodespacerange"));
            var tokenScanner   = new CoreTokenScanner(byteArrayInput);

            Assert.True(tokenScanner.MoveNext());
            Assert.True(tokenScanner.CurrentToken is NumericToken);
            var numeric = (NumericToken)tokenScanner.CurrentToken;

            Assert.True(tokenScanner.MoveNext());
            Assert.True(tokenScanner.CurrentToken is OperatorToken);
            var opToken = (OperatorToken)tokenScanner.CurrentToken;

            Assert.Equal("begincodespacerange", opToken.Data);

            var cmapBuilder = new CharacterMapBuilder();

            parser.Parse(numeric, tokenScanner, cmapBuilder);

            Assert.Empty(cmapBuilder.CodespaceRanges);
        }
示例#11
0
        public void Parse(NumericToken numeric, ITokenScanner scanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            var results = new List <CidCharacterMapping>();

            for (var i = 0; i < numeric.Int; i++)
            {
                if (!scanner.TryReadToken(out HexToken sourceCode))
                {
                    throw new InvalidOperationException("The first token in a line for Cid Characters should be a hex, instead it was: " + scanner.CurrentToken);
                }

                if (!scanner.TryReadToken(out NumericToken destinationCode))
                {
                    throw new InvalidOperationException("The destination token in a line for Cid Character should be an integer, instead it was: " + scanner.CurrentToken);
                }

                var sourceInteger = sourceCode.Bytes.ToInt(sourceCode.Bytes.Count);
                var mapping       = new CidCharacterMapping(sourceInteger, destinationCode.Int);

                results.Add(mapping);
            }

            builder.CidCharacterMappings = results;
        }
示例#12
0
        public void Parse(NumericToken numberOfOperations, ITokenScanner scanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            for (var i = 0; i < numberOfOperations.Int; i++)
            {
                // The start of the input code range.
                if (!scanner.TryReadToken(out HexToken lowSourceCode))
                {
                    throw new InvalidFontFormatException($"bfrange was missing the low source code: {scanner.CurrentToken}");
                }

                // The inclusive end of the input code range.
                if (!scanner.TryReadToken(out HexToken highSourceCode))
                {
                    throw new InvalidFontFormatException($"bfrange was missing the high source code: {scanner.CurrentToken}");
                }

                if (!scanner.MoveNext())
                {
                    throw new InvalidFontFormatException("bfrange ended unexpectedly after the high source code.");
                }

                List <byte> destinationBytes = null;
                ArrayToken  destinationArray = null;

                switch (scanner.CurrentToken)
                {
                case ArrayToken arrayToken:
                    destinationArray = arrayToken;
                    break;

                case HexToken hexToken:
                    destinationBytes = hexToken.Bytes.ToList();
                    break;

                case NumericToken _:
                    throw new NotImplementedException("From the spec it seems this possible but the meaning is unclear...");

                default:
                    throw new InvalidOperationException();
                }

                var done      = false;
                var startCode = new List <byte>(lowSourceCode.Bytes);
                var endCode   = highSourceCode.Bytes;

                if (destinationArray != null)
                {
                    int arrayIndex = 0;
                    while (!done)
                    {
                        if (Compare(startCode, endCode) >= 0)
                        {
                            done = true;
                        }

                        var destination = destinationArray.Data[arrayIndex];

                        if (destination is NameToken name)
                        {
                            builder.AddBaseFontCharacter(startCode, name.Data);
                        }
                        else if (destination is HexToken hex)
                        {
                            builder.AddBaseFontCharacter(startCode, hex.Bytes);
                        }

                        Increment(startCode, startCode.Count - 1);

                        arrayIndex++;
                    }

                    continue;
                }

                while (!done)
                {
                    if (Compare(startCode, endCode) >= 0)
                    {
                        done = true;
                    }

                    builder.AddBaseFontCharacter(startCode, destinationBytes);

                    Increment(startCode, startCode.Count - 1);

                    Increment(destinationBytes, destinationBytes.Count - 1);
                }
            }
        }
示例#13
0
        public CMap Parse(IInputBytes inputBytes, bool isLenientParsing)
        {
            var scanner = new CoreTokenScanner(inputBytes);

            var builder = new CharacterMapBuilder();

            IToken previousToken = null;

            while (scanner.MoveNext())
            {
                var token = scanner.CurrentToken;

                if (token is OperatorToken operatorToken)
                {
                    switch (operatorToken.Data)
                    {
                    case "usecmap":
                    {
                        if (previousToken is NameToken name)
                        {
                            var external = ParseExternal(name.Data);

                            builder.UseCMap(external);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding external cmap call: " + previousToken);
                        }
                        break;
                    }

                    case "begincodespacerange":
                    {
                        if (previousToken is NumericToken numeric)
                        {
                            CodespaceRangeParser.Parse(numeric, scanner, builder, isLenientParsing);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding start of codespace range: " + previousToken);
                        }
                    }
                    break;

                    case "beginbfchar":
                    {
                        if (previousToken is NumericToken numeric)
                        {
                            BaseFontCharacterParser.Parse(numeric, scanner, builder, isLenientParsing);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding start of base font characters: " + previousToken);
                        }
                    }
                    break;

                    case "beginbfrange":
                    {
                        if (previousToken is NumericToken numeric)
                        {
                            BaseFontRangeParser.Parse(numeric, scanner, builder, isLenientParsing);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding start of base font character ranges: " + previousToken);
                        }
                    }
                    break;

                    case "begincidchar":
                    {
                        if (previousToken is NumericToken numeric)
                        {
                            CidCharacterParser.Parse(numeric, scanner, builder, isLenientParsing);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding start of Cid character mapping: " + previousToken);
                        }
                        break;
                    }

                    case "begincidrange":
                    {
                        if (previousToken is NumericToken numeric)
                        {
                            CidRangeParser.Parse(numeric, scanner, builder, isLenientParsing);
                        }
                        else
                        {
                            throw new InvalidOperationException("Unexpected token preceding start of Cid ranges: " + previousToken);
                        }
                    }
                    break;
                    }
                }
                else if (token is NameToken name)
                {
                    CidFontNameParser.Parse(name, scanner, builder, isLenientParsing);
                }

                previousToken = token;
            }

            return(builder.Build());
        }
示例#14
0
        public void Parse(NameToken nameToken, ITokenScanner scanner, CharacterMapBuilder builder,
                          bool isLenientParsing)
        {
            switch (nameToken.Data)
            {
            case "WMode":
            {
                if (scanner.TryReadToken(out NumericToken numeric))
                {
                    builder.WMode = numeric.Int;
                }
                break;
            }

            case "CMapName":
            {
                if (scanner.TryReadToken(out NameToken name))
                {
                    builder.Name = name.Data;
                }
                break;
            }

            case "CMapVersion":
            {
                if (!scanner.MoveNext())
                {
                    break;
                }

                var next = scanner.CurrentToken;
                if (next is NumericToken number)
                {
                    builder.Version = number.Data.ToString(NumberFormatInfo.InvariantInfo);
                }
                else if (next is StringToken stringToken)
                {
                    builder.Version = stringToken.Data;
                }
                break;
            }

            case "CMapType":
            {
                if (scanner.TryReadToken(out NumericToken numeric))
                {
                    builder.Type = numeric.Int;
                }
                break;
            }

            case "Registry":
            {
                if (scanner.TryReadToken(out StringToken stringToken))
                {
                    builder.SystemInfoBuilder.Registry = stringToken.Data;
                }
                break;
            }

            case "Ordering":
            {
                if (scanner.TryReadToken(out StringToken stringToken))
                {
                    builder.SystemInfoBuilder.Ordering = stringToken.Data;
                }
                break;
            }

            case "Supplement":
            {
                if (scanner.TryReadToken(out NumericToken numericToken))
                {
                    builder.SystemInfoBuilder.Supplement = numericToken.Int;
                }
                break;
            }

            case "CIDSystemInfo":
            {
                if (scanner.TryReadToken(out DictionaryToken dictionary))
                {
                    builder.CharacterIdentifierSystemInfo = GetCharacterIdentifier(dictionary, isLenientParsing);
                }
                break;
            }
            }
        }
示例#15
0
        public void Parse(NumericToken numeric, ITokenScanner scanner, CharacterMapBuilder builder, bool isLenientParsing)
        {
            for (var i = 0; i < numeric.Int; i++)
            {
                if (!scanner.TryReadToken(out HexToken lowSourceCode))
                {
                    // TODO: message
                    throw new InvalidOperationException();
                }

                if (!scanner.TryReadToken(out HexToken highSourceCode))
                {
                    // TODO: message
                    throw new InvalidOperationException();
                }

                if (!scanner.MoveNext())
                {
                    // TODO: message
                    throw new InvalidOperationException();
                }

                List <byte> destinationBytes = null;
                ArrayToken  destinationArray = null;
                switch (scanner.CurrentToken)
                {
                case ArrayToken arrayToken:
                    destinationArray = arrayToken;
                    break;

                case HexToken hexToken:
                    destinationBytes = hexToken.Bytes.ToList();
                    break;

                case NumericToken _:
                    throw new NotImplementedException("From the spec it seems this possible but the meaning is unclear...");

                default:
                    throw new InvalidOperationException();
                }

                var done      = false;
                var startCode = new List <byte>(lowSourceCode.Bytes);
                var endCode   = highSourceCode.Bytes;

                int arrayIndex = 0;
                while (!done)
                {
                    if (Compare(startCode, endCode) >= 0)
                    {
                        done = true;
                    }

                    builder.AddBaseFontCharacter(startCode, destinationBytes);

                    Increment(startCode, startCode.Count - 1);

                    if (destinationArray == null)
                    {
                        Increment(destinationBytes, destinationBytes.Count - 1);
                    }
                    else
                    {
                        arrayIndex++;
                        if (arrayIndex < destinationArray.Data.Count)
                        {
                            destinationBytes = ((HexToken)destinationArray.Data[arrayIndex]).Bytes.ToList();
                        }
                    }
                }
            }
        }