private Type1Token ReadNextToken() { previousToken = CurrentToken; bool skip; do { skip = false; while (bytes.MoveNext()) { var b = bytes.CurrentByte; var c = (char)b; switch (c) { case '%': comments.Add(ReadComment()); break; case '(': return(ReadString()); case ')': throw new InvalidOperationException("Encountered an end of string ')' outside of string."); case '[': return(new Type1Token(c, Type1Token.TokenType.StartArray)); case ']': return(new Type1Token(c, Type1Token.TokenType.EndArray)); case '{': return(new Type1Token(c, Type1Token.TokenType.StartProc)); case '}': return(new Type1Token(c, Type1Token.TokenType.EndProc)); case '/': { var name = ReadLiteral(); return(new Type1Token(name, Type1Token.TokenType.Literal)); } case '<': { var following = bytes.Peek(); if (following == '<') { bytes.MoveNext(); return(new Type1Token("<<", Type1Token.TokenType.StartDict)); } return(new Type1Token(c, Type1Token.TokenType.Name)); } case '>': { var following = bytes.Peek(); if (following == '>') { bytes.MoveNext(); return(new Type1Token(">>", Type1Token.TokenType.EndDict)); } return(new Type1Token(c, Type1Token.TokenType.Name)); } default: { if (ReadHelper.IsWhitespace(b)) { skip = true; break; } if (b == 0) { skip = true; break; } if (TryReadNumber(c, out var number)) { return(number); } var name = ReadLiteral(c); if (name == null) { throw new InvalidOperationException($"The binary portion of the type 1 font was invalid at position {bytes.CurrentOffset}."); } if (name.Equals(Type1Symbols.RdProcedure, StringComparison.OrdinalIgnoreCase) || name.Equals(Type1Symbols.RdProcedureAlt)) { if (previousToken.Type == Type1Token.TokenType.Integer) { return(ReadCharString(previousToken.AsInt())); } throw new InvalidOperationException($"Expected integer token before {name} at offset {bytes.CurrentOffset}."); } return(new Type1Token(name, Type1Token.TokenType.Name)); } } } } while (skip); return(null); }
public Type1Tokenizer(IInputBytes bytes) { this.bytes = bytes; comments = new List <string>(); CurrentToken = ReadNextToken(); }
public Type1Token GetNext() { CurrentToken = ReadNextToken(); return(CurrentToken); }
private bool TryReadNumber(char c, out Type1Token numberToken) { char GetNext() { bytes.MoveNext(); return((char)bytes.CurrentByte); } numberToken = null; var currentPosition = bytes.CurrentOffset; var sb = new StringBuilder(); StringBuilder radix = null; var hasDigit = false; // optional + or - if (c == '+' || c == '-') { sb.Append(c); c = GetNext(); } // optional digits while (char.IsDigit(c)) { sb.Append(c); c = GetNext(); hasDigit = true; } // optional . if (c == '.') { sb.Append(c); c = GetNext(); } else if (c == '#') { // PostScript radix number takes the form base#number radix = sb; sb = new StringBuilder(); c = GetNext(); } else if (sb.Length == 0 || !hasDigit) { // failure bytes.Seek(currentPosition); return(false); } else { // integer bytes.Seek(bytes.CurrentOffset - 1); numberToken = new Type1Token(sb.ToString(), Type1Token.TokenType.Integer); return(true); } // required digit if (char.IsDigit(c)) { sb.Append(c); c = GetNext(); } else { bytes.Seek(currentPosition); return(false); } // optional digits while (char.IsDigit(c)) { sb.Append(c); c = GetNext(); } // optional E if (c == 'E') { sb.Append(c); c = GetNext(); // optional minus if (c == '-') { sb.Append(c); c = GetNext(); } // required digit if (char.IsDigit(c)) { sb.Append(c); c = GetNext(); } else { bytes.Seek(currentPosition); return(false); } // optional digits while (char.IsDigit(c)) { sb.Append(c); c = GetNext(); } } bytes.Seek(bytes.CurrentOffset - 1); if (radix != null) { var number = Convert.ToInt32(sb.ToString(), int.Parse(radix.ToString(), CultureInfo.InvariantCulture)); numberToken = new Type1Token(number.ToString(), Type1Token.TokenType.Integer); } else { numberToken = new Type1Token(sb.ToString(), Type1Token.TokenType.Real); } return(true); }