Test
This commit is contained in:
848
PrintPDF/PdfSharp/Pdf.Content/CLexer.cs
Normal file
848
PrintPDF/PdfSharp/Pdf.Content/CLexer.cs
Normal file
@@ -0,0 +1,848 @@
|
||||
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using PdfSharp.Internal;
|
||||
|
||||
#pragma warning disable 1591
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Lexical analyzer for PDF content files. Adobe specifies no grammar, but it seems that it
|
||||
/// is a simple post-fix notation.
|
||||
/// </summary>
|
||||
public class CLexer
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Lexer class.
|
||||
/// </summary>
|
||||
public CLexer(byte[] content)
|
||||
{
|
||||
_content = content;
|
||||
_charIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Lexer class.
|
||||
/// </summary>
|
||||
public CLexer(MemoryStream content)
|
||||
{
|
||||
_content = content.ToArray();
|
||||
_charIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next token and returns its type.
|
||||
/// </summary>
|
||||
public CSymbol ScanNextToken()
|
||||
{
|
||||
Again:
|
||||
ClearToken();
|
||||
char ch = MoveToNonWhiteSpace();
|
||||
switch (ch)
|
||||
{
|
||||
case '%':
|
||||
// Eat comments, the parser doesn't handle them
|
||||
//return symbol = ScanComment();
|
||||
ScanComment();
|
||||
goto Again;
|
||||
|
||||
case '/':
|
||||
return _symbol = ScanName();
|
||||
|
||||
//case 'R':
|
||||
// if (Lexer.IsWhiteSpace(nextChar))
|
||||
// {
|
||||
// ScanNextChar();
|
||||
// return Symbol.R;
|
||||
// }
|
||||
// break;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
return _symbol = ScanNumber();
|
||||
|
||||
case '[':
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.BeginArray;
|
||||
|
||||
case ']':
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.EndArray;
|
||||
|
||||
case '(':
|
||||
return _symbol = ScanLiteralString();
|
||||
|
||||
case '<':
|
||||
if (_nextChar == '<')
|
||||
return _symbol = ScanDictionary();
|
||||
return _symbol = ScanHexadecimalString();
|
||||
|
||||
case '.':
|
||||
return _symbol = ScanNumber();
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
return _symbol = ScanOperator();
|
||||
}
|
||||
if (char.IsDigit(ch))
|
||||
return _symbol = ScanNumber();
|
||||
|
||||
if (char.IsLetter(ch))
|
||||
return _symbol = ScanOperator();
|
||||
|
||||
if (ch == Chars.EOF)
|
||||
return _symbol = CSymbol.Eof;
|
||||
|
||||
ContentReaderDiagnostics.HandleUnexpectedCharacter(ch);
|
||||
return _symbol = CSymbol.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans a comment line. (Not yet used, comments are skipped by lexer.)
|
||||
/// </summary>
|
||||
public CSymbol ScanComment()
|
||||
{
|
||||
Debug.Assert(_currChar == Chars.Percent);
|
||||
|
||||
ClearToken();
|
||||
char ch;
|
||||
while ((ch = AppendAndScanNextChar()) != Chars.LF && ch != Chars.EOF) { }
|
||||
return _symbol = CSymbol.Comment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the bytes of an inline image.
|
||||
/// NYI: Just scans over it.
|
||||
/// </summary>
|
||||
public CSymbol ScanInlineImage()
|
||||
{
|
||||
// TODO: Implement inline images.
|
||||
// Skip this:
|
||||
// BI
|
||||
// … Key-value pairs …
|
||||
// ID
|
||||
// … Image data …
|
||||
// EI
|
||||
|
||||
bool ascii85 = false;
|
||||
do
|
||||
{
|
||||
ScanNextToken();
|
||||
// HACK: Is image ASCII85 decoded?
|
||||
if (!ascii85 && _symbol == CSymbol.Name && (Token == "/ASCII85Decode" || Token == "/A85"))
|
||||
ascii85 = true;
|
||||
} while (_symbol != CSymbol.Operator || Token != "ID");
|
||||
|
||||
if (ascii85)
|
||||
{
|
||||
// Look for '~>' because 'EI' may be part of the encoded image.
|
||||
while (_currChar != Chars.EOF && (_currChar != '~' || _nextChar != '>'))
|
||||
ScanNextChar();
|
||||
if (_currChar == Chars.EOF)
|
||||
ContentReaderDiagnostics.HandleUnexpectedCharacter(_currChar);
|
||||
}
|
||||
|
||||
// Look for '<ws>EI<ws>', as 'EI' may be part of the binary image data here too.
|
||||
while (_currChar != Chars.EOF)
|
||||
{
|
||||
if (IsWhiteSpace(_currChar))
|
||||
{
|
||||
if (ScanNextChar() == 'E')
|
||||
if (ScanNextChar() == 'I')
|
||||
if (IsWhiteSpace(ScanNextChar()))
|
||||
break;
|
||||
}
|
||||
else
|
||||
ScanNextChar();
|
||||
}
|
||||
if (_currChar == Chars.EOF)
|
||||
ContentReaderDiagnostics.HandleUnexpectedCharacter(_currChar);
|
||||
|
||||
// We currently do nothing with inline images.
|
||||
return CSymbol.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans a name.
|
||||
/// </summary>
|
||||
public CSymbol ScanName()
|
||||
{
|
||||
Debug.Assert(_currChar == Chars.Slash);
|
||||
|
||||
ClearToken();
|
||||
while (true)
|
||||
{
|
||||
char ch = AppendAndScanNextChar();
|
||||
if (IsWhiteSpace(ch) || IsDelimiter(ch))
|
||||
return _symbol = CSymbol.Name;
|
||||
|
||||
if (ch == '#')
|
||||
{
|
||||
ScanNextChar();
|
||||
char[] hex = new char[2];
|
||||
hex[0] = _currChar;
|
||||
hex[1] = _nextChar;
|
||||
ScanNextChar();
|
||||
// TODO Check syntax
|
||||
ch = (char)(ushort)int.Parse(new string(hex), NumberStyles.AllowHexSpecifier);
|
||||
_currChar = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CSymbol ScanDictionary()
|
||||
{
|
||||
// TODO Do an actual recursive parse instead of this simple scan.
|
||||
|
||||
ClearToken();
|
||||
_token.Append(_currChar); // '<'
|
||||
_token.Append(ScanNextChar()); // '<'
|
||||
|
||||
bool inString = false, inHexString = false;
|
||||
int nestedDict = 0, nestedStringParen = 0;
|
||||
char ch;
|
||||
while (true)
|
||||
{
|
||||
_token.Append(ch = ScanNextChar());
|
||||
if (ch == '<')
|
||||
{
|
||||
if (_nextChar == '<')
|
||||
{
|
||||
_token.Append(ScanNextChar());
|
||||
++nestedDict;
|
||||
}
|
||||
else
|
||||
inHexString = true;
|
||||
}
|
||||
else if (!inHexString && ch == '(')
|
||||
{
|
||||
if (inString)
|
||||
++nestedStringParen;
|
||||
else
|
||||
{
|
||||
inString = true;
|
||||
nestedStringParen = 0;
|
||||
}
|
||||
}
|
||||
else if (inString && ch == ')')
|
||||
{
|
||||
if (nestedStringParen > 0)
|
||||
--nestedStringParen;
|
||||
else
|
||||
inString = false;
|
||||
}
|
||||
else if (inString && ch == '\\')
|
||||
_token.Append(ScanNextChar());
|
||||
else if (ch == '>')
|
||||
{
|
||||
if (inHexString)
|
||||
inHexString = false;
|
||||
else if (_nextChar == '>')
|
||||
{
|
||||
_token.Append(ScanNextChar());
|
||||
if (nestedDict > 0)
|
||||
--nestedDict;
|
||||
else
|
||||
{
|
||||
ScanNextChar();
|
||||
|
||||
#if true
|
||||
return CSymbol.Dictionary;
|
||||
#else
|
||||
return CSymbol.String;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ch == Chars.EOF)
|
||||
ContentReaderDiagnostics.HandleUnexpectedCharacter(ch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans an integer or real number.
|
||||
/// </summary>
|
||||
public CSymbol ScanNumber()
|
||||
{
|
||||
long value = 0;
|
||||
int decimalDigits = 0;
|
||||
bool period = false;
|
||||
bool negative = false;
|
||||
|
||||
ClearToken();
|
||||
char ch = _currChar;
|
||||
if (ch == '+' || ch == '-')
|
||||
{
|
||||
if (ch == '-')
|
||||
negative = true;
|
||||
_token.Append(ch);
|
||||
ch = ScanNextChar();
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (char.IsDigit(ch))
|
||||
{
|
||||
_token.Append(ch);
|
||||
if (decimalDigits < 10)
|
||||
{
|
||||
value = 10 * value + ch - '0';
|
||||
if (period)
|
||||
decimalDigits++;
|
||||
}
|
||||
}
|
||||
else if (ch == '.')
|
||||
{
|
||||
if (period)
|
||||
ContentReaderDiagnostics.ThrowContentReaderException("More than one period in number.");
|
||||
|
||||
period = true;
|
||||
_token.Append(ch);
|
||||
}
|
||||
else
|
||||
break;
|
||||
ch = ScanNextChar();
|
||||
}
|
||||
|
||||
if (negative)
|
||||
value = -value;
|
||||
if (period)
|
||||
{
|
||||
if (decimalDigits > 0)
|
||||
{
|
||||
_tokenAsReal = value / PowersOf10[decimalDigits];
|
||||
//_tokenAsLong = value / PowersOf10[decimalDigits];
|
||||
}
|
||||
else
|
||||
{
|
||||
_tokenAsReal = value;
|
||||
_tokenAsLong = value;
|
||||
}
|
||||
return CSymbol.Real;
|
||||
}
|
||||
_tokenAsLong = value;
|
||||
_tokenAsReal = Convert.ToDouble(value);
|
||||
|
||||
Debug.Assert(Int64.Parse(_token.ToString(), CultureInfo.InvariantCulture) == value);
|
||||
|
||||
if (value >= Int32.MinValue && value < Int32.MaxValue)
|
||||
return CSymbol.Integer;
|
||||
|
||||
ContentReaderDiagnostics.ThrowNumberOutOfIntegerRange(value);
|
||||
return CSymbol.Error;
|
||||
}
|
||||
static readonly double[] PowersOf10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000 };
|
||||
|
||||
/// <summary>
|
||||
/// Scans an operator.
|
||||
/// </summary>
|
||||
public CSymbol ScanOperator()
|
||||
{
|
||||
ClearToken();
|
||||
char ch = _currChar;
|
||||
// Scan token
|
||||
while (IsOperatorChar(ch))
|
||||
ch = AppendAndScanNextChar();
|
||||
|
||||
return _symbol = CSymbol.Operator;
|
||||
}
|
||||
|
||||
// TODO
|
||||
public CSymbol ScanLiteralString()
|
||||
{
|
||||
Debug.Assert(_currChar == Chars.ParenLeft);
|
||||
|
||||
ClearToken();
|
||||
int parenLevel = 0;
|
||||
char ch = ScanNextChar();
|
||||
// Test UNICODE string
|
||||
if (ch == '\xFE' && _nextChar == '\xFF')
|
||||
{
|
||||
// I'm not sure if the code is correct in any case.
|
||||
// ? Can a UNICODE character not start with ')' as hibyte
|
||||
// ? What about \# escape sequences
|
||||
ScanNextChar();
|
||||
char chHi = ScanNextChar();
|
||||
if (chHi == ')')
|
||||
{
|
||||
// The empty unicode string...
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.String;
|
||||
}
|
||||
char chLo = ScanNextChar();
|
||||
ch = (char)(chHi * 256 + chLo);
|
||||
while (true)
|
||||
{
|
||||
SkipChar:
|
||||
switch (ch)
|
||||
{
|
||||
case '(':
|
||||
parenLevel++;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if (parenLevel == 0)
|
||||
{
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.String;
|
||||
}
|
||||
parenLevel--;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
{
|
||||
// TODO: not sure that this is correct...
|
||||
ch = ScanNextChar();
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
ch = Chars.LF;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
ch = Chars.CR;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
ch = Chars.HT;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
ch = Chars.BS;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
ch = Chars.FF;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
ch = Chars.ParenLeft;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
ch = Chars.ParenRight;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
ch = Chars.BackSlash;
|
||||
break;
|
||||
|
||||
case Chars.LF:
|
||||
ch = ScanNextChar();
|
||||
goto SkipChar;
|
||||
|
||||
default:
|
||||
if (char.IsDigit(ch))
|
||||
{
|
||||
// Octal character code
|
||||
int n = ch - '0';
|
||||
if (char.IsDigit(_nextChar))
|
||||
{
|
||||
n = n * 8 + ScanNextChar() - '0';
|
||||
if (char.IsDigit(_nextChar))
|
||||
n = n * 8 + ScanNextChar() - '0';
|
||||
}
|
||||
ch = (char)n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//case '#':
|
||||
// ContentReaderDiagnostics.HandleUnexpectedCharacter('#');
|
||||
// break;
|
||||
|
||||
default:
|
||||
// Every other char is appended to the token.
|
||||
break;
|
||||
}
|
||||
_token.Append(ch);
|
||||
chHi = ScanNextChar();
|
||||
if (chHi == ')')
|
||||
{
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.String;
|
||||
}
|
||||
chLo = ScanNextChar();
|
||||
ch = (char)(chHi * 256 + chLo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 8-bit characters
|
||||
while (true)
|
||||
{
|
||||
SkipChar:
|
||||
switch (ch)
|
||||
{
|
||||
case '(':
|
||||
parenLevel++;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if (parenLevel == 0)
|
||||
{
|
||||
ScanNextChar();
|
||||
return _symbol = CSymbol.String;
|
||||
}
|
||||
parenLevel--;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
{
|
||||
ch = ScanNextChar();
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
ch = Chars.LF;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
ch = Chars.CR;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
ch = Chars.HT;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
ch = Chars.BS;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
ch = Chars.FF;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
ch = Chars.ParenLeft;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
ch = Chars.ParenRight;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
ch = Chars.BackSlash;
|
||||
break;
|
||||
|
||||
case Chars.LF:
|
||||
ch = ScanNextChar();
|
||||
goto SkipChar;
|
||||
|
||||
default:
|
||||
if (char.IsDigit(ch))
|
||||
{
|
||||
// Octal character code.
|
||||
int n = ch - '0';
|
||||
if (char.IsDigit(_nextChar))
|
||||
{
|
||||
n = n * 8 + ScanNextChar() - '0';
|
||||
if (char.IsDigit(_nextChar))
|
||||
n = n * 8 + ScanNextChar() - '0';
|
||||
}
|
||||
ch = (char)n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//case '#':
|
||||
// ContentReaderDiagnostics.HandleUnexpectedCharacter('#');
|
||||
// break;
|
||||
|
||||
default:
|
||||
// Every other char is appended to the token.
|
||||
break;
|
||||
}
|
||||
_token.Append(ch);
|
||||
//token.Append(Encoding.GetEncoding(1252).GetString(new byte[] { (byte)ch }));
|
||||
ch = ScanNextChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
public CSymbol ScanHexadecimalString()
|
||||
{
|
||||
Debug.Assert(_currChar == Chars.Less);
|
||||
|
||||
ClearToken();
|
||||
char[] hex = new char[2];
|
||||
ScanNextChar();
|
||||
while (true)
|
||||
{
|
||||
MoveToNonWhiteSpace();
|
||||
if (_currChar == '>')
|
||||
{
|
||||
ScanNextChar();
|
||||
break;
|
||||
}
|
||||
if (char.IsLetterOrDigit(_currChar))
|
||||
{
|
||||
hex[0] = char.ToUpper(_currChar);
|
||||
hex[1] = char.ToUpper(_nextChar);
|
||||
int ch = int.Parse(new string(hex), NumberStyles.AllowHexSpecifier);
|
||||
_token.Append(Convert.ToChar(ch));
|
||||
ScanNextChar();
|
||||
ScanNextChar();
|
||||
}
|
||||
}
|
||||
string chars = _token.ToString();
|
||||
int count = chars.Length;
|
||||
if (count > 2 && chars[0] == (char)0xFE && chars[1] == (char)0xFF)
|
||||
{
|
||||
Debug.Assert(count % 2 == 0);
|
||||
_token.Length = 0;
|
||||
for (int idx = 2; idx < count; idx += 2)
|
||||
_token.Append((char)(chars[idx] * 256 + chars[idx + 1]));
|
||||
}
|
||||
return _symbol = CSymbol.HexString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move current position one character further in content stream.
|
||||
/// </summary>
|
||||
internal char ScanNextChar()
|
||||
{
|
||||
if (ContLength <= _charIndex)
|
||||
{
|
||||
_currChar = Chars.EOF;
|
||||
if (IsOperatorChar(_nextChar))
|
||||
_token.Append(_nextChar);
|
||||
_nextChar = Chars.EOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currChar = _nextChar;
|
||||
_nextChar = (char)_content[_charIndex++];
|
||||
if (_currChar == Chars.CR)
|
||||
{
|
||||
if (_nextChar == Chars.LF)
|
||||
{
|
||||
// Treat CR LF as LF
|
||||
_currChar = _nextChar;
|
||||
if (ContLength <= _charIndex)
|
||||
_nextChar = Chars.EOF;
|
||||
else
|
||||
_nextChar = (char)_content[_charIndex++];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Treat single CR as LF
|
||||
_currChar = Chars.LF;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _currChar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the current token to the empty string.
|
||||
/// </summary>
|
||||
void ClearToken()
|
||||
{
|
||||
_token.Length = 0;
|
||||
_tokenAsLong = 0;
|
||||
_tokenAsReal = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends current character to the token and reads next one.
|
||||
/// </summary>
|
||||
internal char AppendAndScanNextChar()
|
||||
{
|
||||
_token.Append(_currChar);
|
||||
return ScanNextChar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the current character is not a white space, the function immediately returns it.
|
||||
/// Otherwise the PDF cursor is moved forward to the first non-white space or EOF.
|
||||
/// White spaces are NUL, HT, LF, FF, CR, and SP.
|
||||
/// </summary>
|
||||
public char MoveToNonWhiteSpace()
|
||||
{
|
||||
while (_currChar != Chars.EOF)
|
||||
{
|
||||
switch (_currChar)
|
||||
{
|
||||
case Chars.NUL:
|
||||
case Chars.HT:
|
||||
case Chars.LF:
|
||||
case Chars.FF:
|
||||
case Chars.CR:
|
||||
case Chars.SP:
|
||||
ScanNextChar();
|
||||
break;
|
||||
|
||||
default:
|
||||
return _currChar;
|
||||
}
|
||||
}
|
||||
return _currChar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current symbol.
|
||||
/// </summary>
|
||||
public CSymbol Symbol
|
||||
{
|
||||
get { return _symbol; }
|
||||
set { _symbol = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current token.
|
||||
/// </summary>
|
||||
public string Token
|
||||
{
|
||||
get { return _token.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interprets current token as integer literal.
|
||||
/// </summary>
|
||||
internal int TokenToInteger
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(_tokenAsLong == int.Parse(_token.ToString(), CultureInfo.InvariantCulture));
|
||||
return (int)_tokenAsLong;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpret current token as real or integer literal.
|
||||
/// </summary>
|
||||
internal double TokenToReal
|
||||
{
|
||||
get
|
||||
{
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
Debug.Assert(_tokenAsReal == double.Parse(_token.ToString(), CultureInfo.InvariantCulture));
|
||||
return _tokenAsReal;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified character is a content stream white-space character.
|
||||
/// </summary>
|
||||
internal static bool IsWhiteSpace(char ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case Chars.NUL: // 0 Null
|
||||
case Chars.HT: // 9 Tab
|
||||
case Chars.LF: // 10 Line feed
|
||||
case Chars.FF: // 12 Form feed
|
||||
case Chars.CR: // 13 Carriage return
|
||||
case Chars.SP: // 32 Space
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified character is an content operator character.
|
||||
/// </summary>
|
||||
internal static bool IsOperatorChar(char ch)
|
||||
{
|
||||
if (char.IsLetter(ch))
|
||||
return true;
|
||||
switch (ch)
|
||||
{
|
||||
case Chars.Asterisk: // *
|
||||
case Chars.QuoteSingle: // '
|
||||
case Chars.QuoteDbl: // "
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the specified character is a PDF delimiter character.
|
||||
/// </summary>
|
||||
internal static bool IsDelimiter(char ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '(':
|
||||
case ')':
|
||||
case '<':
|
||||
case '>':
|
||||
case '[':
|
||||
case ']':
|
||||
//case '{':
|
||||
//case '}':
|
||||
case '/':
|
||||
case '%':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the content.
|
||||
/// </summary>
|
||||
public int ContLength
|
||||
{
|
||||
get { return _content.Length; }
|
||||
}
|
||||
|
||||
// ad
|
||||
public int Position
|
||||
{
|
||||
get { return _charIndex; }
|
||||
set
|
||||
{
|
||||
_charIndex = value;
|
||||
_currChar = (char)_content[_charIndex - 1];
|
||||
_nextChar = (char)_content[_charIndex - 1];
|
||||
}
|
||||
}
|
||||
|
||||
readonly byte[] _content;
|
||||
int _charIndex;
|
||||
char _currChar;
|
||||
char _nextChar;
|
||||
|
||||
readonly StringBuilder _token = new StringBuilder();
|
||||
long _tokenAsLong;
|
||||
double _tokenAsReal;
|
||||
CSymbol _symbol = CSymbol.None;
|
||||
}
|
||||
}
|
231
PrintPDF/PdfSharp/Pdf.Content/CParser.cs
Normal file
231
PrintPDF/PdfSharp/Pdf.Content/CParser.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using PdfSharp.Internal;
|
||||
using PdfSharp.Pdf.Advanced;
|
||||
using PdfSharp.Pdf.Content.Objects;
|
||||
|
||||
#pragma warning disable 1591
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the functionality to parse PDF content streams.
|
||||
/// </summary>
|
||||
public sealed class CParser
|
||||
{
|
||||
public CParser(PdfPage page)
|
||||
{
|
||||
_page = page;
|
||||
PdfContent content = page.Contents.CreateSingleContent();
|
||||
byte[] bytes = content.Stream.Value;
|
||||
_lexer = new CLexer(bytes);
|
||||
}
|
||||
|
||||
public CParser(byte[] content)
|
||||
{
|
||||
_lexer = new CLexer(content);
|
||||
}
|
||||
|
||||
public CParser(MemoryStream content)
|
||||
{
|
||||
_lexer = new CLexer(content.ToArray());
|
||||
}
|
||||
|
||||
|
||||
public CParser(CLexer lexer)
|
||||
{
|
||||
_lexer = lexer;
|
||||
}
|
||||
|
||||
public CSymbol Symbol
|
||||
{
|
||||
get { return _lexer.Symbol; }
|
||||
}
|
||||
|
||||
public CSequence ReadContent()
|
||||
{
|
||||
CSequence sequence = new CSequence();
|
||||
ParseObject(sequence, CSymbol.Eof);
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses whatever comes until the specified stop symbol is reached.
|
||||
/// </summary>
|
||||
void ParseObject(CSequence sequence, CSymbol stop)
|
||||
{
|
||||
CSymbol symbol;
|
||||
while ((symbol = ScanNextToken()) != CSymbol.Eof)
|
||||
{
|
||||
if (symbol == stop)
|
||||
return;
|
||||
|
||||
CString s;
|
||||
COperator op;
|
||||
switch (symbol)
|
||||
{
|
||||
case CSymbol.Comment:
|
||||
// ignore comments
|
||||
break;
|
||||
|
||||
case CSymbol.Integer:
|
||||
CInteger n = new CInteger();
|
||||
n.Value = _lexer.TokenToInteger;
|
||||
_operands.Add(n);
|
||||
break;
|
||||
|
||||
case CSymbol.Real:
|
||||
CReal r = new CReal();
|
||||
r.Value = _lexer.TokenToReal;
|
||||
_operands.Add(r);
|
||||
break;
|
||||
|
||||
case CSymbol.String:
|
||||
case CSymbol.HexString:
|
||||
case CSymbol.UnicodeString:
|
||||
case CSymbol.UnicodeHexString:
|
||||
s = new CString();
|
||||
s.Value = _lexer.Token;
|
||||
_operands.Add(s);
|
||||
break;
|
||||
|
||||
case CSymbol.Dictionary:
|
||||
s = new CString();
|
||||
s.Value = _lexer.Token;
|
||||
s.CStringType = CStringType.Dictionary;
|
||||
_operands.Add(s);
|
||||
op = CreateOperator(OpCodeName.Dictionary);
|
||||
//_operands.Clear();
|
||||
sequence.Add(op);
|
||||
|
||||
break;
|
||||
|
||||
case CSymbol.Name:
|
||||
CName name = new CName();
|
||||
name.Name = _lexer.Token;
|
||||
_operands.Add(name);
|
||||
break;
|
||||
|
||||
case CSymbol.Operator:
|
||||
op = CreateOperator();
|
||||
//_operands.Clear();
|
||||
sequence.Add(op);
|
||||
break;
|
||||
|
||||
case CSymbol.BeginArray:
|
||||
CArray array = new CArray();
|
||||
if (_operands.Count != 0)
|
||||
ContentReaderDiagnostics.ThrowContentReaderException("Array within array...");
|
||||
|
||||
ParseObject(array, CSymbol.EndArray);
|
||||
array.Add(_operands);
|
||||
_operands.Clear();
|
||||
_operands.Add((CObject)array);
|
||||
break;
|
||||
|
||||
case CSymbol.EndArray:
|
||||
ContentReaderDiagnostics.HandleUnexpectedCharacter(']');
|
||||
break;
|
||||
|
||||
#if DEBUG
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
COperator CreateOperator()
|
||||
{
|
||||
string name = _lexer.Token;
|
||||
COperator op = OpCodes.OperatorFromName(name);
|
||||
return CreateOperator(op);
|
||||
}
|
||||
|
||||
COperator CreateOperator(OpCodeName nameop)
|
||||
{
|
||||
string name = nameop.ToString();
|
||||
COperator op = OpCodes.OperatorFromName(name);
|
||||
return CreateOperator(op);
|
||||
}
|
||||
|
||||
COperator CreateOperator(COperator op)
|
||||
{
|
||||
if (op.OpCode.OpCodeName == OpCodeName.BI)
|
||||
{
|
||||
_lexer.ScanInlineImage();
|
||||
}
|
||||
#if DEBUG
|
||||
if (op.OpCode.Operands != -1 && op.OpCode.Operands != _operands.Count)
|
||||
{
|
||||
if (op.OpCode.OpCodeName != OpCodeName.ID)
|
||||
{
|
||||
GetType();
|
||||
Debug.Assert(false, "Invalid number of operands.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
op.Operands.Add(_operands);
|
||||
_operands.Clear();
|
||||
return op;
|
||||
}
|
||||
|
||||
CSymbol ScanNextToken()
|
||||
{
|
||||
return _lexer.ScanNextToken();
|
||||
}
|
||||
|
||||
CSymbol ScanNextToken(out string token)
|
||||
{
|
||||
CSymbol symbol = _lexer.ScanNextToken();
|
||||
token = _lexer.Token;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next symbol that must be the specified one.
|
||||
/// </summary>
|
||||
CSymbol ReadSymbol(CSymbol symbol)
|
||||
{
|
||||
CSymbol current = _lexer.ScanNextToken();
|
||||
if (symbol != current)
|
||||
ContentReaderDiagnostics.ThrowContentReaderException(PSSR.UnexpectedToken(_lexer.Token));
|
||||
return current;
|
||||
}
|
||||
|
||||
readonly CSequence _operands = new CSequence();
|
||||
PdfPage _page;
|
||||
readonly CLexer _lexer;
|
||||
}
|
||||
}
|
80
PrintPDF/PdfSharp/Pdf.Content/Chars.cs
Normal file
80
PrintPDF/PdfSharp/Pdf.Content/Chars.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Character table by name. Same as PdfSharp.Pdf.IO.Chars. Not yet clear if necessary.
|
||||
/// </summary>
|
||||
internal static class Chars
|
||||
{
|
||||
public const char EOF = (char)65535; //unchecked((char)(-1));
|
||||
public const char NUL = '\0'; // EOF
|
||||
public const char CR = '\x0D'; // ignored by lexer
|
||||
public const char LF = '\x0A'; // Line feed
|
||||
public const char BEL = '\a'; // Bell
|
||||
public const char BS = '\b'; // Backspace
|
||||
public const char FF = '\f'; // Form feed
|
||||
public const char HT = '\t'; // Horizontal tab
|
||||
public const char VT = '\v'; // Vertical tab
|
||||
public const char NonBreakableSpace = (char)160; // char(160)
|
||||
|
||||
// The following names come from "PDF Reference Third Edition"
|
||||
// Appendix D.1, Latin Character Set and Encoding
|
||||
public const char SP = ' ';
|
||||
public const char QuoteDbl = '"';
|
||||
public const char QuoteSingle = '\'';
|
||||
public const char ParenLeft = '(';
|
||||
public const char ParenRight = ')';
|
||||
public const char BraceLeft = '{';
|
||||
public const char BraceRight = '}';
|
||||
public const char BracketLeft = '[';
|
||||
public const char BracketRight = ']';
|
||||
public const char Less = '<';
|
||||
public const char Greater = '>';
|
||||
public const char Equal = '=';
|
||||
public const char Period = '.';
|
||||
public const char Semicolon = ';';
|
||||
public const char Colon = ':';
|
||||
public const char Slash = '/';
|
||||
public const char Bar = '|';
|
||||
public const char BackSlash = '\\';
|
||||
public const char Percent = '%';
|
||||
public const char Dollar = '$';
|
||||
public const char At = '@';
|
||||
public const char NumberSign = '#';
|
||||
public const char Asterisk = '*';
|
||||
public const char Question = '?';
|
||||
public const char Hyphen = '-'; // char(45)
|
||||
public const char SoftHyphen = ''; // char(173)
|
||||
public const char Currency = '¤';
|
||||
}
|
||||
}
|
74
PrintPDF/PdfSharp/Pdf.Content/ContentReader.cs
Normal file
74
PrintPDF/PdfSharp/Pdf.Content/ContentReader.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
using PdfSharp.Pdf.Content.Objects;
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the functionality for reading PDF content streams.
|
||||
/// </summary>
|
||||
public static class ContentReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads the content stream(s) of the specified page.
|
||||
/// </summary>
|
||||
/// <param name="page">The page.</param>
|
||||
static public CSequence ReadContent(PdfPage page)
|
||||
{
|
||||
CParser parser = new CParser(page);
|
||||
CSequence sequence = parser.ReadContent();
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
static public CSequence ReadContent(byte[] content)
|
||||
{
|
||||
CParser parser = new CParser(content);
|
||||
CSequence sequence = parser.ReadContent();
|
||||
return sequence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the specified content.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
static public CSequence ReadContent(MemoryStream content)
|
||||
{
|
||||
CParser parser = new CParser(content);
|
||||
CSequence sequence = parser.ReadContent();
|
||||
return sequence;
|
||||
}
|
||||
}
|
||||
}
|
62
PrintPDF/PdfSharp/Pdf.Content/ContentReaderException.cs
Normal file
62
PrintPDF/PdfSharp/Pdf.Content/ContentReaderException.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception thrown by ContentReader.
|
||||
/// </summary>
|
||||
public class ContentReaderException : PdfSharpException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentReaderException"/> class.
|
||||
/// </summary>
|
||||
public ContentReaderException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentReaderException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public ContentReaderException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentReaderException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="innerException">The inner exception.</param>
|
||||
public ContentReaderException(string message, Exception innerException) :
|
||||
base(message, innerException)
|
||||
{ }
|
||||
}
|
||||
}
|
231
PrintPDF/PdfSharp/Pdf.Content/ContentWriter.cs
Normal file
231
PrintPDF/PdfSharp/Pdf.Content/ContentWriter.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using PdfSharp.Pdf.Internal;
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a writer for generation of PDF streams.
|
||||
/// </summary>
|
||||
internal class ContentWriter
|
||||
{
|
||||
public ContentWriter(Stream contentStream)
|
||||
{
|
||||
_stream = contentStream;
|
||||
#if DEBUG
|
||||
//layout = PdfWriterLayout.Verbose;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Close(bool closeUnderlyingStream)
|
||||
{
|
||||
if (_stream != null && closeUnderlyingStream)
|
||||
{
|
||||
#if UWP
|
||||
_stream.Dispose();
|
||||
#else
|
||||
_stream.Close();
|
||||
#endif
|
||||
_stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Close(true);
|
||||
}
|
||||
|
||||
public int Position
|
||||
{
|
||||
get { return (int)_stream.Position; }
|
||||
}
|
||||
|
||||
//public PdfWriterLayout Layout
|
||||
//{
|
||||
// get { return layout; }
|
||||
// set { layout = value; }
|
||||
//}
|
||||
//PdfWriterLayout layout;
|
||||
|
||||
//public PdfWriterOptions Options
|
||||
//{
|
||||
// get { return options; }
|
||||
// set { options = value; }
|
||||
//}
|
||||
//PdfWriterOptions options;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified value to the PDF stream.
|
||||
/// </summary>
|
||||
public void Write(bool value)
|
||||
{
|
||||
//WriteSeparator(CharCat.Character);
|
||||
//WriteRaw(value ? bool.TrueString : bool.FalseString);
|
||||
//lastCat = CharCat.Character;
|
||||
}
|
||||
|
||||
public void WriteRaw(string rawString)
|
||||
{
|
||||
if (String.IsNullOrEmpty(rawString))
|
||||
return;
|
||||
//AppendBlank(rawString[0]);
|
||||
byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString);
|
||||
_stream.Write(bytes, 0, bytes.Length);
|
||||
_lastCat = GetCategory((char)bytes[bytes.Length - 1]);
|
||||
}
|
||||
|
||||
public void WriteLineRaw(string rawString)
|
||||
{
|
||||
if (String.IsNullOrEmpty(rawString))
|
||||
return;
|
||||
//AppendBlank(rawString[0]);
|
||||
byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString);
|
||||
_stream.Write(bytes, 0, bytes.Length);
|
||||
_stream.Write(new byte[] { (byte)'\n' }, 0, 1);
|
||||
_lastCat = GetCategory((char)bytes[bytes.Length - 1]);
|
||||
}
|
||||
|
||||
public void WriteRaw(char ch)
|
||||
{
|
||||
Debug.Assert(ch < 256, "Raw character greater than 255 detected.");
|
||||
_stream.WriteByte((byte)ch);
|
||||
_lastCat = GetCategory(ch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the indentation for a new indentation level.
|
||||
/// </summary>
|
||||
internal int Indent
|
||||
{
|
||||
get { return _indent; }
|
||||
set { _indent = value; }
|
||||
}
|
||||
protected int _indent = 2;
|
||||
protected int _writeIndent = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Increases indent level.
|
||||
/// </summary>
|
||||
void IncreaseIndent()
|
||||
{
|
||||
_writeIndent += _indent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decreases indent level.
|
||||
/// </summary>
|
||||
void DecreaseIndent()
|
||||
{
|
||||
_writeIndent -= _indent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an indent string of current indent.
|
||||
/// </summary>
|
||||
string IndentBlanks
|
||||
{
|
||||
get { return new string(' ', _writeIndent); }
|
||||
}
|
||||
|
||||
void WriteIndent()
|
||||
{
|
||||
WriteRaw(IndentBlanks);
|
||||
}
|
||||
|
||||
void WriteSeparator(CharCat cat, char ch)
|
||||
{
|
||||
switch (_lastCat)
|
||||
{
|
||||
//case CharCat.NewLine:
|
||||
// if (this.layout == PdfWriterLayout.Verbose)
|
||||
// WriteIndent();
|
||||
// break;
|
||||
|
||||
case CharCat.Delimiter:
|
||||
break;
|
||||
|
||||
//case CharCat.Character:
|
||||
// if (this.layout == PdfWriterLayout.Verbose)
|
||||
// {
|
||||
// //if (cat == CharCat.Character || ch == '/')
|
||||
// this.stream.WriteByte((byte)' ');
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (cat == CharCat.Character)
|
||||
// this.stream.WriteByte((byte)' ');
|
||||
// }
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteSeparator(CharCat cat)
|
||||
{
|
||||
WriteSeparator(cat, '\0');
|
||||
}
|
||||
|
||||
public void NewLine()
|
||||
{
|
||||
if (_lastCat != CharCat.NewLine)
|
||||
WriteRaw('\n');
|
||||
}
|
||||
|
||||
CharCat GetCategory(char ch)
|
||||
{
|
||||
//if (Lexer.IsDelimiter(ch))
|
||||
// return CharCat.Delimiter;
|
||||
//if (ch == Chars.LF)
|
||||
// return CharCat.NewLine;
|
||||
return CharCat.Character;
|
||||
}
|
||||
|
||||
enum CharCat
|
||||
{
|
||||
NewLine,
|
||||
Character,
|
||||
Delimiter,
|
||||
}
|
||||
CharCat _lastCat;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying stream.
|
||||
/// </summary>
|
||||
internal Stream Stream
|
||||
{
|
||||
get { return _stream; }
|
||||
}
|
||||
Stream _stream;
|
||||
}
|
||||
}
|
55
PrintPDF/PdfSharp/Pdf.Content/enums/Symbol.cs
Normal file
55
PrintPDF/PdfSharp/Pdf.Content/enums/Symbol.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
namespace PdfSharp.Pdf.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Terminal symbols recognized by PDF content stream lexer.
|
||||
/// </summary>
|
||||
public enum CSymbol
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
None,
|
||||
Comment,
|
||||
Integer,
|
||||
Real,
|
||||
/*Boolean?,*/
|
||||
String,
|
||||
HexString,
|
||||
UnicodeString,
|
||||
UnicodeHexString,
|
||||
Name,
|
||||
Operator,
|
||||
BeginArray,
|
||||
EndArray,
|
||||
Dictionary, // HACK: << ... >> is scanned as string literal.
|
||||
Eof,
|
||||
Error = -1,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user