vendor: import KillerPDF 1.7.5 source (GPL-3.0) as the base for MMD PDF

This commit is contained in:
2026-08-27 06:58:22 +02:00
commit 532485a830
577 changed files with 149058 additions and 0 deletions
+189
View File
@@ -0,0 +1,189 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Character table by name.
/// </summary>
public sealed class Chars
{
// ReSharper disable InconsistentNaming
/// <summary>
/// The EOF marker.
/// </summary>
public const char EOF = (char)65535; //unchecked((char)(-1));
/// <summary>
/// The null byte.
/// </summary>
public const char NUL = '\0'; // EOF
/// <summary>
/// The carriage return character (ignored by lexer).
/// </summary>
public const char CR = '\x0D'; // ignored by lexer
/// <summary>
/// The line feed character.
/// </summary>
public const char LF = '\x0A'; // Line feed
/// <summary>
/// The bell character.
/// </summary>
public const char BEL = '\a'; // Bell
/// <summary>
/// The backspace character.
/// </summary>
public const char BS = '\b'; // Backspace
/// <summary>
/// The form feed character.
/// </summary>
public const char FF = '\f'; // Form feed
/// <summary>
/// The horizontal tab character.
/// </summary>
public const char HT = '\t'; // Horizontal tab
/// <summary>
/// The vertical tab character.
/// </summary>
public const char VT = '\v'; // Vertical tab
/// <summary>
/// The non-breakable space character (aka no-break space or non-breaking space).
/// </summary>
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
/// <summary>
/// The space character.
/// </summary>
public const char SP = ' ';
/// <summary>
/// The double quote character.
/// </summary>
public const char QuoteDbl = '"';
/// <summary>
/// The single quote character.
/// </summary>
public const char QuoteSingle = '\'';
/// <summary>
/// The left parenthesis.
/// </summary>
public const char ParenLeft = '(';
/// <summary>
/// The right parenthesis.
/// </summary>
public const char ParenRight = ')';
/// <summary>
/// The left brace.
/// </summary>
public const char BraceLeft = '{';
/// <summary>
/// The right brace.
/// </summary>
public const char BraceRight = '}';
/// <summary>
/// The left bracket.
/// </summary>
public const char BracketLeft = '[';
/// <summary>
/// The right bracket.
/// </summary>
public const char BracketRight = ']';
/// <summary>
/// The less-than sign.
/// </summary>
public const char Less = '<';
/// <summary>
/// The greater-than sign.
/// </summary>
public const char Greater = '>';
/// <summary>
/// The equal sign.
/// </summary>
public const char Equal = '=';
/// <summary>
/// The period.
/// </summary>
public const char Period = '.';
/// <summary>
/// The semicolon.
/// </summary>
public const char Semicolon = ';';
/// <summary>
/// The colon.
/// </summary>
public const char Colon = ':';
/// <summary>
/// The slash.
/// </summary>
public const char Slash = '/';
/// <summary>
/// The bar character.
/// </summary>
public const char Bar = '|';
/// <summary>
/// The back slash.
/// </summary>
public const char BackSlash = '\\';
/// <summary>
/// The percent sign.
/// </summary>
public const char Percent = '%';
/// <summary>
/// The dollar sign.
/// </summary>
public const char Dollar = '$';
/// <summary>
/// The at sign.
/// </summary>
public const char At = '@';
/// <summary>
/// The number sign.
/// </summary>
public const char NumberSign = '#';
/// <summary>
/// The question mark.
/// </summary>
public const char Question = '?';
/// <summary>
/// The hyphen.
/// </summary>
public const char Hyphen = '-'; // char(45)
/// <summary>
/// The soft hyphen.
/// </summary>
public const char SoftHyphen = '­'; // char(173)
/// <summary>
/// The currency sign.
/// </summary>
public const char Currency = '¤';
// ReSharper restore InconsistentNaming
}
}
+925
View File
@@ -0,0 +1,925 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Internal;
using PdfSharpCore.Pdf.Internal;
using System.Collections.Generic;
using System.Linq;
namespace PdfSharpCore.Pdf.IO
{
/// <summary>
/// Lexical analyzer for PDF files. Technically a PDF file is a stream of bytes. Some chunks
/// of bytes represent strings in several encodings. The actual encoding depends on the
/// context where the string is used. Therefore the bytes are 'raw encoded' into characters,
/// i.e. a character or token read by the lexer has always character values in the range from
/// 0 to 255.
/// </summary>
public class Lexer
{
/// <summary>
/// Initializes a new instance of the Lexer class.
/// </summary>
public Lexer(Stream pdfInputStream)
{
_pdfSteam = pdfInputStream;
_pdfLength = _pdfSteam.Length;
_idxChar = 0;
Position = 0;
}
/// <summary>
/// Gets or sets the position within the PDF stream.
/// </summary>
public long Position
{
get { return _idxChar; }
set
{
_idxChar = value;
_pdfSteam.Position = value;
// ReadByte return -1 (eof) at the end of the stream.
_currChar = (char)_pdfSteam.ReadByte();
_nextChar = (char)_pdfSteam.ReadByte();
_token = new StringBuilder();
}
}
/// <summary>
/// Reads the next token and returns its type. If the token starts with a digit, the parameter
/// testReference specifies how to treat it. If it is false, the lexer scans for a single integer.
/// If it is true, the lexer checks if the digit is the prefix of a reference. If it is a reference,
/// the token is set to the object ID followed by the generation number separated by a blank
/// (the 'R' is omitted from the token).
/// </summary>
// /// <param name="testReference">Indicates whether to test the next token if it is a reference.</param>
public Symbol ScanNextToken()
{
Again:
_token = new StringBuilder();
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 '+': //TODO is it so easy?
case '-':
return _symbol = ScanNumber();
case '(':
return _symbol = ScanLiteralString();
case '[':
ScanNextChar(true);
return _symbol = Symbol.BeginArray;
case ']':
ScanNextChar(true);
return _symbol = Symbol.EndArray;
case '<':
if (_nextChar == '<')
{
ScanNextChar(true);
ScanNextChar(true);
return _symbol = Symbol.BeginDictionary;
}
return _symbol = ScanHexadecimalString();
case '>':
if (_nextChar == '>')
{
ScanNextChar(true);
ScanNextChar(true);
return _symbol = Symbol.EndDictionary;
}
ParserDiagnostics.HandleUnexpectedCharacter(_nextChar);
break;
case '.':
return _symbol = ScanNumber();
}
if (char.IsDigit(ch))
#if true_
return ScanNumberOrReference();
#else
if (PeekReference())
return _symbol = ScanNumber();
else
return _symbol = ScanNumber();
#endif
if (char.IsLetter(ch))
return _symbol = ScanKeyword();
if (ch == Chars.EOF)
return _symbol = Symbol.Eof;
// #???
ParserDiagnostics.HandleUnexpectedCharacter(ch);
return _symbol = Symbol.None;
}
/// <summary>
/// Reads the raw content of a stream.
/// </summary>
public byte[] ReadStream(int length)
{
var pos = MoveToStartOfStream();
_pdfSteam.Position = pos;
byte[] bytes = new byte[length];
int read = _pdfSteam.Read(bytes, 0, length);
Debug.Assert(read == length);
// Synchronize idxChar etc.
Position = pos + length;
return bytes;
}
internal long MoveToStartOfStream()
{
long pos;
// Skip illegal blanks behind «stream».
while (_currChar == Chars.SP)
ScanNextChar(true);
// Skip new line behind «stream».
if (_currChar == Chars.CR)
{
if (_nextChar == Chars.LF)
pos = _idxChar + 2;
else
pos = _idxChar + 1;
}
else
pos = _idxChar + 1;
return pos;
}
/// <summary>
/// Scans the input stream for the specified marker.<br></br>
/// Returns the bytes from the current position up to the start of the marker or the end of the stream.<br></br>
/// The position of the input-stream is the byte right after the marker (if found) or the end of the stream.
/// </summary>
/// <param name="marker">The marker to scan for</param>
/// <param name="markerFound">Receives a boolean that indicates whether the marker was found</param>
/// <returns></returns>
internal byte[] ScanUntilMarker(byte[] marker, out bool markerFound)
{
markerFound = false;
var result = new List<byte>();
while (true)
{
var markerIndex = 0;
while (_currChar != Chars.EOF && _currChar != marker[markerIndex])
{
result.Add((byte)_currChar);
ScanNextChar(false);
}
while (_currChar != Chars.EOF && markerIndex < marker.Length && _currChar == marker[markerIndex])
{
markerIndex++;
ScanNextChar(false);
}
if (_currChar == Chars.EOF || markerIndex == marker.Length)
{
if (markerIndex == marker.Length)
markerFound = true;
break;
}
// only part of the marker was found, add to result and continue
result.AddRange(marker.Take(markerIndex));
}
return result.ToArray();
}
/// <summary>
/// Reads a string in raw encoding.
/// </summary>
public string ReadRawString(long position, int length)
{
_pdfSteam.Position = position;
byte[] bytes = new byte[length];
_pdfSteam.Read(bytes, 0, length);
return PdfEncoders.RawEncoding.GetString(bytes, 0, bytes.Length);
}
/// <summary>
/// Scans a comment line.
/// </summary>
public Symbol ScanComment()
{
Debug.Assert(_currChar == Chars.Percent);
_token = new StringBuilder();
while (true)
{
char ch = AppendAndScanNextChar();
if (ch == Chars.LF || ch == Chars.EOF)
break;
}
// TODO: not correct
if (_token.ToString().StartsWith("%%EOF"))
return Symbol.Eof;
return _symbol = Symbol.Comment;
}
/// <summary>
/// Scans a name.
/// </summary>
public Symbol ScanName()
{
Debug.Assert(_currChar == Chars.Slash);
_token = new StringBuilder();
while (true)
{
char ch = AppendAndScanNextChar();
if (IsWhiteSpace(ch) || IsDelimiter(ch) || ch == Chars.EOF)
return _symbol = Symbol.Name;
if (ch == '#')
{
ScanNextChar(true);
char[] hex = new char[2];
hex[0] = _currChar;
hex[1] = _nextChar;
ScanNextChar(true);
// TODO Check syntax
ch = (char)(ushort)int.Parse(new string(hex), NumberStyles.AllowHexSpecifier);
_currChar = ch;
}
}
}
/// <summary>
/// Scans a number.
/// </summary>
public Symbol ScanNumber()
{
// I found a PDF file created with Acrobat 7 with this entry
// /Checksum 2996984786
// What is this? It is neither an integer nor a real.
// I introduced an UInteger...
bool period = false;
//bool sign;
_token = new StringBuilder();
char ch = _currChar;
if (ch == '+' || ch == '-')
{
//sign = true;
_token.Append(ch);
ch = ScanNextChar(true);
}
while (true)
{
if (char.IsDigit(ch))
{
_token.Append(ch);
}
else if (ch == '.')
{
if (period)
ParserDiagnostics.ThrowParserException("More than one period in number.");
period = true;
_token.Append(ch);
}
else
break;
ch = ScanNextChar(true);
}
if (period)
return Symbol.Real;
long l = Int64.Parse(_token.ToString(), CultureInfo.InvariantCulture);
if (l >= Int32.MinValue && l <= Int32.MaxValue)
return Symbol.Integer;
if (l >= Int64.MinValue && l <= Int64.MaxValue)
return Symbol.Long;
// Got an AutoCAD PDF file that contains this: /C 264584027963392
// Best we can do is to convert it to real value.
return Symbol.Real;
}
public Symbol ScanNumberOrReference()
{
Symbol result = ScanNumber();
return result;
}
/// <summary>
/// Scans a keyword.
/// </summary>
public Symbol ScanKeyword()
{
_token = new StringBuilder();
char ch = _currChar;
// Scan token
while (true)
{
if (char.IsLetter(ch))
_token.Append(ch);
else
break;
ch = ScanNextChar(false);
}
// Check known tokens.
switch (_token.ToString())
{
case "obj":
return _symbol = Symbol.Obj;
case "endobj":
return _symbol = Symbol.EndObj;
case "null":
return _symbol = Symbol.Null;
case "true":
case "false":
return _symbol = Symbol.Boolean;
case "R":
return _symbol = Symbol.R;
case "stream":
return _symbol = Symbol.BeginStream;
case "endstream":
return _symbol = Symbol.EndStream;
case "xref":
return _symbol = Symbol.XRef;
case "trailer":
return _symbol = Symbol.Trailer;
case "startxref":
return _symbol = Symbol.StartXRef;
}
// Anything else is treated as a keyword. Samples are f or n in iref.
return _symbol = Symbol.Keyword;
}
/// <summary>
/// Scans a literal string, contained between "(" and ")".
/// </summary>
public Symbol ScanLiteralString()
{
// Reference: 3.2.3 String Objects / Page 53
// Reference: TABLE 3.32 String Types / Page 157
Debug.Assert(_currChar == Chars.ParenLeft);
_token = new StringBuilder();
int parenLevel = 0;
char ch = ScanNextChar(false);
// Phase 1: deal with escape characters.
while (ch != Chars.EOF)
{
switch (ch)
{
case '(':
parenLevel++;
break;
case ')':
if (parenLevel == 0)
{
ScanNextChar(false);
// Is goto evil? We could move Phase 2 code here or create a subroutine for Phase 1.
goto Phase2;
}
parenLevel--;
break;
case '\\':
{
ch = ScanNextChar(false);
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;
// AutoCAD PDFs my contain such strings: (\ )
case ' ':
ch = ' ';
break;
case Chars.CR:
case Chars.LF:
ch = ScanNextChar(false);
continue;
default:
if (char.IsDigit(ch)) // First octal character.
{
// Octal character code.
if (ch >= '8')
break; // Since the first possible octal character is not valid,
// the backslash is ignored.
int n = ch - '0';
if (char.IsDigit(_nextChar)) // Second octal character.
{
ch = ScanNextChar(false);
if (ch >= '8')
ParserDiagnostics.HandleUnexpectedCharacter(ch);
n = n * 8 + ch - '0';
if (char.IsDigit(_nextChar)) // Third octal character.
{
ch = ScanNextChar(false);
if (ch >= '8')
ParserDiagnostics.HandleUnexpectedCharacter(ch);
n = n * 8 + ch - '0';
}
}
ch = (char)n;
}
break;
}
break;
}
default:
break;
}
_token.Append(ch);
ch = ScanNextChar(false);
}
// Phase 2: deal with UTF-16BE if necessary.
// UTF-16BE Unicode strings start with U+FEFF ("þÿ"). There can be empty strings with UTF-16BE prefix.
Phase2:
if (_token.Length >= 2 && _token[0] == '\xFE' && _token[1] == '\xFF')
{
// Combine two ANSI characters to get one Unicode character.
StringBuilder temp = _token;
int length = temp.Length;
if ((length & 1) == 1)
{
// TODO What does the PDF Reference say about this case? Assume (char)0 or treat the file as corrupted?
temp.Append(0);
++length;
DebugBreak.Break();
}
_token = new StringBuilder();
for (int i = 2; i < length; i += 2)
{
_token.Append((char)(256 * temp[i] + temp[i + 1]));
}
return _symbol = Symbol.UnicodeString;
}
// Adobe Reader also supports UTF-16LE.
if (_token.Length >= 2 && _token[0] == '\xFF' && _token[1] == '\xFE')
{
// Combine two ANSI characters to get one Unicode character.
StringBuilder temp = _token;
int length = temp.Length;
if ((length & 1) == 1)
{
// TODO What does the PDF Reference say about this case? Assume (char)0 or treat the file as corrupted?
temp.Append(0);
++length;
DebugBreak.Break();
}
_token = new StringBuilder();
for (int i = 2; i < length; i += 2)
{
_token.Append((char)(256 * temp[i + 1] + temp[i]));
}
return _symbol = Symbol.UnicodeString;
}
return _symbol = Symbol.String;
}
public Symbol ScanHexadecimalString()
{
Debug.Assert(_currChar == Chars.Less);
_token = new StringBuilder();
char[] hex = new char[2];
ScanNextChar(true);
while (true)
{
MoveToNonWhiteSpace();
if (_currChar == '>')
{
ScanNextChar(true);
break;
}
if (IsHexChar(_currChar))
{
hex[0] = _currChar;
hex[1] = IsHexChar(_nextChar) ? _nextChar : ' ';
int ch = int.Parse(new string(hex), NumberStyles.HexNumber);
_token.Append(Convert.ToChar(ch));
ScanNextChar(true);
if (_currChar != '>')
ScanNextChar(true);
}
else
// prevent endless loop in case _currChar is neither '>' nor a hex-char nor whitespace
ScanNextChar(true);
}
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 = Symbol.UnicodeHexString;
}
return _symbol = Symbol.HexString;
}
internal static bool IsHexChar(char c)
{
return char.IsDigit(c) ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
}
/// <summary>
/// Move current position one character further in PDF stream.
/// </summary>
internal char ScanNextChar(bool handleCRLF)
{
if (_pdfLength <= _idxChar)
{
_currChar = Chars.EOF;
_nextChar = Chars.EOF;
}
else
{
_currChar = _nextChar;
_nextChar = (char)_pdfSteam.ReadByte();
_idxChar++;
if (handleCRLF && _currChar == Chars.CR)
{
if (_nextChar == Chars.LF)
{
// Treat CR LF as LF.
_currChar = _nextChar;
_nextChar = (char)_pdfSteam.ReadByte();
_idxChar++;
}
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;
//}
bool PeekReference()
{
// A Reference has the form "nnn mmm R". The implementation of the the parser used a
// reduce/shift algorithm in the first place. But this case is the only one we need to
// look ahead 3 tokens.
var positon = Position;
// Skip digits.
while (char.IsDigit(_currChar))
ScanNextChar(true);
// Space expected.
if (_currChar != Chars.SP)
goto False;
// Skip spaces.
while (_currChar == Chars.SP)
ScanNextChar(true);
// Digit expected.
if (!char.IsDigit(_currChar))
goto False;
// Skip digits.
while (char.IsDigit(_currChar))
ScanNextChar(true);
// Space expected.
if (_currChar != Chars.SP)
goto False;
// Skip spaces.
while (_currChar == Chars.SP)
ScanNextChar(true);
// "R" expected.
// We can ignore _nextChar because there is no other valid token that starts with an 'R'.
if (_currChar != 'R')
goto False;
Position = positon;
return true;
False:
Position = positon;
return false;
}
/// <summary>
/// Appends current character to the token and reads next one.
/// </summary>
internal char AppendAndScanNextChar()
{
if (_currChar == Chars.EOF)
ParserDiagnostics.ThrowParserException("Undetected EOF reached.");
_token.Append(_currChar);
return ScanNextChar(true);
}
/// <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(true);
break;
case (char)11:
case (char)173:
ScanNextChar(true);
break;
default:
return _currChar;
}
}
return _currChar;
}
// #if DEBUG
// public string SurroundingsOfCurrentPosition(bool hex)
// {
// const int range = 20;
// int start = Math.Max(Position - range, 0);
// int length = Math.Min(2 * range, PdfLength - start);
// long posOld = _pdfSteam.Position;
// _pdfSteam.Position = start;
// byte[] bytes = new byte[length];
// _pdfSteam.Read(bytes, 0, length);
// _pdfSteam.Position = posOld;
// string result = "";
// if (hex)
// {
// for (int idx = 0; idx < length; idx++)
// result += ((int)bytes[idx]).ToString("x2");
// //result += string.Format("{0:", (int) bytes[idx]);
// }
// else
// {
// for (int idx = 0; idx < length; idx++)
// result += (char)bytes[idx];
// }
// return result;
// }
// #endif
/// <summary>
/// Gets the current symbol.
/// </summary>
public Symbol 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 boolean literal.
/// </summary>
public bool TokenToBoolean
{
get
{
Debug.Assert(_token.ToString() == "true" || _token.ToString() == "false");
return _token.ToString()[0] == 't';
}
}
/// <summary>
/// Interprets current token as integer literal.
/// </summary>
public int TokenToInteger
{
get
{
//Debug.As sert(_token.ToString().IndexOf('.') == -1);
return int.Parse(_token.ToString(), CultureInfo.InvariantCulture);
}
}
/// <summary>
/// Interprets current token as unsigned integer literal.
/// </summary>
public uint TokenToUInteger
{
get
{
//Debug.As sert(_token.ToString().IndexOf('.') == -1);
return uint.Parse(_token.ToString(), CultureInfo.InvariantCulture);
}
}
public long TokenToLong => long.Parse(_token.ToString(), CultureInfo.InvariantCulture);
/// <summary>
/// Interprets current token as real or integer literal.
/// </summary>
public double TokenToReal
{
get { return double.Parse(_token.ToString(), CultureInfo.InvariantCulture); }
}
/// <summary>
/// Interprets current token as object ID.
/// </summary>
public PdfObjectID TokenToObjectID
{
get
{
string[] numbers = Token.Split('|');
int objectNumber = Int32.Parse(numbers[0]);
int generationNumber = Int32.Parse(numbers[1]);
return new PdfObjectID(objectNumber, generationNumber);
}
}
/// <summary>
/// Indicates whether the specified character is a PDF white-space character.
/// </summary>
internal static bool IsWhiteSpace(char ch)
{
switch (ch)
{
case Chars.NUL: // 0 Null
case Chars.HT: // 9 Horizontal 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 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 PDF output.
/// </summary>
public long PdfLength
{
get { return _pdfLength; }
}
readonly long _pdfLength;
long _idxChar;
char _currChar;
char _nextChar;
StringBuilder _token;
Symbol _symbol = Symbol.None;
readonly Stream _pdfSteam;
}
}
File diff suppressed because it is too large Load Diff
+632
View File
@@ -0,0 +1,632 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using PdfSharpCore.Exceptions;
using PdfSharpCore.Pdf.Advanced;
using PdfSharpCore.Pdf.Security;
using PdfSharpCore.Pdf.Internal;
using PdfSharpCore.Internal;
using PdfSharpCore.Pdf.IO.enums;
namespace PdfSharpCore.Pdf.IO
{
/// <summary>
/// Encapsulates the arguments of the PdfPasswordProvider delegate.
/// </summary>
public class PdfPasswordProviderArgs
{
/// <summary>
/// Sets the password to open the document with.
/// </summary>
public string Password;
/// <summary>
/// When set to true the PdfReader.Open function returns null indicating that no PdfDocument was created.
/// </summary>
public bool Abort;
}
/// <summary>
/// A delegated used by the PdfReader.Open function to retrieve a password if the document is protected.
/// </summary>
public delegate void PdfPasswordProvider(PdfPasswordProviderArgs args);
/// <summary>
/// Represents the functionality for reading PDF documents.
/// </summary>
public static class PdfReader
{
/// <summary>
/// Determines whether the file specified by its path is a PDF file by inspecting the first eight
/// bytes of the data. If the file header has the form «%PDF-x.y» the function returns the version
/// number as integer (e.g. 14 for PDF 1.4). If the file header is invalid or inaccessible
/// for any reason, 0 is returned. The function never throws an exception.
/// </summary>
public static int TestPdfFile(string path)
{
FileStream stream = null;
try
{
int pageNumber;
string realPath = Drawing.XPdfForm.ExtractPageNumber(path, out pageNumber);
if (File.Exists(realPath)) // prevent unwanted exceptions during debugging
{
stream = new FileStream(realPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
byte[] bytes = new byte[1024];
stream.Read(bytes, 0, 1024);
return GetPdfFileVersion(bytes);
}
}
// ReSharper disable once EmptyGeneralCatchClause
catch { }
finally
{
try
{
if (stream != null)
{
stream.Dispose();
}
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{
}
}
return 0;
}
/// <summary>
/// Determines whether the specified stream is a PDF file by inspecting the first eight
/// bytes of the data. If the data begins with «%PDF-x.y» the function returns the version
/// number as integer (e.g. 14 for PDF 1.4). If the data is invalid or inaccessible
/// for any reason, 0 is returned. The function never throws an exception.
/// </summary>
public static int TestPdfFile(Stream stream)
{
long pos = -1;
try
{
pos = stream.Position;
byte[] bytes = new byte[1024];
stream.Read(bytes, 0, 1024);
return GetPdfFileVersion(bytes);
}
// ReSharper disable once EmptyGeneralCatchClause
catch { }
finally
{
try
{
if (pos != -1)
stream.Position = pos;
}
// ReSharper disable once EmptyGeneralCatchClause
catch { }
}
return 0;
}
/// <summary>
/// Determines whether the specified data is a PDF file by inspecting the first eight
/// bytes of the data. If the data begins with «%PDF-x.y» the function returns the version
/// number as integer (e.g. 14 for PDF 1.4). If the data is invalid or inaccessible
/// for any reason, 0 is returned. The function never throws an exception.
/// </summary>
public static int TestPdfFile(byte[] data)
{
return GetPdfFileVersion(data);
}
/// <summary>
/// Implements scanning the PDF file version.
/// </summary>
///
internal static int GetPdfFileVersion(byte[] bytes)
{
try
{
// Acrobat accepts headers like «%!PS-Adobe-N.n PDF-M.m»...
string header = PdfEncoders.RawEncoding.GetString(bytes, 0, bytes.Length); // Encoding.ASCII.GetString(bytes);
if (header[0] == '%' || header.IndexOf("%PDF", StringComparison.Ordinal) >= 0)
{
int ich = header.IndexOf("PDF-", StringComparison.Ordinal);
if (ich > 0 && header[ich + 5] == '.')
{
char major = header[ich + 4];
char minor = header[ich + 6];
if (major >= '1' && major < '2' && minor >= '0' && minor <= '9')
return (major - '0') * 10 + (minor - '0');
}
}
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{ }
// If it doesn't work with the specified encoding ...
try
{
// The file might be incorrectly encoded as ASCII
string header = System.Text.Encoding.ASCII.GetString(bytes);
if (header[0] == '%' || header.IndexOf("%PDF", StringComparison.Ordinal) >= 0)
{
int ich = header.IndexOf("PDF-", StringComparison.Ordinal);
if (ich > 0 && header[ich + 5] == '.')
{
char major = header[ich + 4];
char minor = header[ich + 6];
if (major >= '1' && major < '2' && minor >= '0' && minor <= '9')
return (major - '0') * 10 + (minor - '0');
}
}
}
// ReSharper disable once EmptyGeneralCatchClause
catch { }
return 0;
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, PdfDocumentOpenMode openmode)
{
return Open(path, null, openmode, null, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, PdfDocumentOpenMode openmode, PdfReadAccuracy accuracy)
{
return Open(path, null, openmode, null, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, PdfDocumentOpenMode openmode, PdfPasswordProvider provider)
{
return Open(path, null, openmode, provider, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, PdfDocumentOpenMode openmode, PdfPasswordProvider provider, PdfReadAccuracy accuracy)
{
return Open(path, null, openmode, provider, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password, PdfDocumentOpenMode openmode)
{
return Open(path, password, openmode, null, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password, PdfDocumentOpenMode openmode, PdfReadAccuracy accuracy)
{
return Open(path, password, openmode, null, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider provider)
{
return Open(path, password, openmode, provider, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider provider, PdfReadAccuracy accuracy)
{
PdfDocument document;
Stream stream = null;
try
{
stream = new FileStream(path, FileMode.Open, FileAccess.Read);
document = Open(stream, password, openmode, provider, accuracy);
if (document != null)
{
document._fullPath = Path.GetFullPath(path);
}
}
finally
{
if (stream != null)
stream.Dispose();
}
return document;
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path)
{
return Open(path, null, PdfDocumentOpenMode.Modify, null, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, PdfReadAccuracy accuracy)
{
return Open(path, null, PdfDocumentOpenMode.Modify, null, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password)
{
return Open(path, password, PdfDocumentOpenMode.Modify, null, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(string path, string password, PdfReadAccuracy accuracy)
{
return Open(path, password, PdfDocumentOpenMode.Modify, null, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, PdfDocumentOpenMode openmode)
{
return Open(stream, null, openmode, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, PdfDocumentOpenMode openmode, PdfReadAccuracy accuracy)
{
return Open(stream, null, openmode, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider)
{
return Open(stream, null, openmode, passwordProvider, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider, PdfReadAccuracy accuracy)
{
return Open(stream, null, openmode, passwordProvider, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode)
{
return Open(stream, password, openmode, null, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfReadAccuracy accuracy)
{
return Open(stream, password, openmode, null, accuracy);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider)
{
return Open(stream, password, openmode, passwordProvider, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, string password, PdfDocumentOpenMode openmode, PdfPasswordProvider passwordProvider, PdfReadAccuracy accuracy)
{
PdfDocument document;
try
{
Lexer lexer = new Lexer(stream);
document = new PdfDocument(lexer);
document._state |= DocumentState.Imported;
document._openMode = openmode;
document._fileSize = stream.Length;
// Get file version.
byte[] header = new byte[1024];
stream.Position = 0;
stream.Read(header, 0, 1024);
document._version = GetPdfFileVersion(header);
if (document._version == 0)
throw new InvalidOperationException(PSSR.InvalidPdf);
document._irefTable.IsUnderConstruction = true;
Parser parser = new Parser(document);
// Read all trailers or cross-reference streams, but no objects.
document._trailer = parser.ReadTrailer(accuracy);
if (document._trailer == null)
ParserDiagnostics.ThrowParserException("Invalid PDF file: no trailer found.");
Debug.Assert(document._irefTable.IsUnderConstruction);
document._irefTable.IsUnderConstruction = false;
// Is document encrypted?
PdfReference xrefEncrypt = document._trailer.Elements[PdfTrailer.Keys.Encrypt] as PdfReference;
if (xrefEncrypt != null)
{
//xrefEncrypt.Value = parser.ReadObject(null, xrefEncrypt.ObjectID, false);
PdfObject encrypt = parser.ReadObject(null, xrefEncrypt.ObjectID, false, false);
encrypt.Reference = xrefEncrypt;
xrefEncrypt.Value = encrypt;
PdfStandardSecurityHandler securityHandler = document.SecurityHandler;
TryAgain:
PasswordValidity validity = securityHandler.ValidatePassword(password);
if (validity == PasswordValidity.Invalid)
{
if (passwordProvider != null)
{
PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
passwordProvider(args);
if (args.Abort)
return null;
password = args.Password;
goto TryAgain;
}
else
{
if (password == null)
throw new PdfReaderException(PSSR.PasswordRequired);
else
throw new PdfReaderException(PSSR.InvalidPassword);
}
}
else if (validity == PasswordValidity.UserPassword && openmode == PdfDocumentOpenMode.Modify)
{
if (passwordProvider != null)
{
PdfPasswordProviderArgs args = new PdfPasswordProviderArgs();
passwordProvider(args);
if (args.Abort)
return null;
password = args.Password;
goto TryAgain;
}
else
throw new PdfReaderException(PSSR.OwnerPasswordRequired);
}
}
else
{
if (password != null)
{
// Password specified but document is not encrypted.
// ignore
}
}
PdfReference[] irefs2 = document._irefTable.AllReferences;
int count2 = irefs2.Length;
// 3rd: Create iRefs for all compressed objects.
Dictionary<int, object> objectStreams = new Dictionary<int, object>();
for (int idx = 0; idx < count2; idx++)
{
PdfReference iref = irefs2[idx];
PdfCrossReferenceStream xrefStream = iref.Value as PdfCrossReferenceStream;
if (xrefStream != null)
{
for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++)
{
PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2];
// Is type xref to compressed object?
if (item.Type == 2)
{
//PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2), (int)item.Field3);
//document._irefTable.Add(irefNew);
int objectNumber = (int)item.Field2;
if (!objectStreams.ContainsKey(objectNumber))
{
objectStreams.Add(objectNumber, null);
PdfObjectID objectID = new PdfObjectID((int)item.Field2);
parser.ReadIRefsFromCompressedObject(objectID);
}
}
}
}
}
// 4th: Read compressed objects.
for (int idx = 0; idx < count2; idx++)
{
PdfReference iref = irefs2[idx];
PdfCrossReferenceStream xrefStream = iref.Value as PdfCrossReferenceStream;
if (xrefStream != null)
{
for (int idx2 = 0; idx2 < xrefStream.Entries.Count; idx2++)
{
PdfCrossReferenceStream.CrossReferenceStreamEntry item = xrefStream.Entries[idx2];
// Is type xref to compressed object?
if (item.Type == 2)
{
PdfReference irefNew = parser.ReadCompressedObject(new PdfObjectID((int)item.Field2),
(int)item.Field3);
Debug.Assert(document._irefTable.Contains(iref.ObjectID));
//document._irefTable.Add(irefNew);
}
}
}
}
PdfReference[] irefs = document._irefTable.AllReferences;
int count = irefs.Length;
// Read all indirect objects.
for (int idx = 0; idx < count; idx++)
{
PdfReference iref = irefs[idx];
if (iref.Value == null)
{
#if DEBUG_
if (iref.ObjectNumber == 1074)
iref.GetType();
#endif
try
{
Debug.Assert(document._irefTable.Contains(iref.ObjectID));
PdfObject pdfObject = parser.ReadObject(null, iref.ObjectID, false, false);
Debug.Assert(pdfObject.Reference == iref);
pdfObject.Reference = iref;
Debug.Assert(pdfObject.Reference.Value != null, "Something went wrong.");
}
catch (PositionNotFoundException ex)
{
Debug.WriteLine(ex.Message);
if (accuracy == PdfReadAccuracy.Strict)
throw;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
// 4STLA rethrow exception to notify caller.
throw;
}
}
else
{
Debug.Assert(document._irefTable.Contains(iref.ObjectID));
//iref.GetType();
}
// Set maximum object number.
document._irefTable._maxObjectNumber = Math.Max(document._irefTable._maxObjectNumber,
iref.ObjectNumber);
}
// Encrypt all objects.
if (xrefEncrypt != null)
{
document.SecurityHandler.EncryptDocument();
}
// Fix references of trailer values and then objects and irefs are consistent.
document._trailer.Finish();
#if DEBUG_
// Some tests...
PdfReference[] reachables = document.xrefTable.TransitiveClosure(document.trailer);
reachables.GetType();
reachables = document.xrefTable.AllXRefs;
document.xrefTable.CheckConsistence();
#endif
if (openmode == PdfDocumentOpenMode.Modify)
{
// Create new or change existing document IDs.
if (document.Internals.SecondDocumentID == "")
document._trailer.CreateNewDocumentIDs();
else
{
byte[] agTemp = Guid.NewGuid().ToByteArray();
document.Internals.SecondDocumentID = PdfEncoders.RawEncoding.GetString(agTemp, 0, agTemp.Length);
}
// KillerPDF patch: do NOT stamp /ModDate just because the file was OPENED in
// Modify mode. PDF/A (ISO 19005-1, 6.7.3 t8) requires /ModDate to stay
// equivalent to the XMP xmp:ModifyDate, and rewriting it here desynced every
// opened file before a single edit was made.
// document.Info.ModificationDate = DateTime.Now;
// Remove all unreachable objects
int removed = document._irefTable.Compact();
if (removed != 0)
Debug.WriteLine("Number of deleted unreachable objects: " + removed);
// Force flattening of page tree
PdfPages pages = document.Pages;
Debug.Assert(pages != null);
//bool b = document.irefTable.Contains(new PdfObjectID(1108));
//b.GetType();
document._irefTable.CheckConsistence();
document._irefTable.Renumber();
document._irefTable.CheckConsistence();
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
throw;
}
return document;
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream)
{
return Open(stream, PdfDocumentOpenMode.Modify, PdfReadAccuracy.Strict);
}
/// <summary>
/// Opens an existing PDF document.
/// </summary>
public static PdfDocument Open(Stream stream, PdfReadAccuracy accuracy)
{
return Open(stream, PdfDocumentOpenMode.Modify, accuracy);
}
}
}
+63
View File
@@ -0,0 +1,63 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Exception thrown by PdfReader.
/// </summary>
public class PdfReaderException : PdfSharpException
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfReaderException"/> class.
/// </summary>
public PdfReaderException()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="PdfReaderException"/> class.
/// </summary>
/// <param name="message">The message.</param>
public PdfReaderException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="PdfReaderException"/> class.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
public PdfReaderException(string message, Exception innerException)
:
base(message, innerException)
{ }
}
}
+656
View File
@@ -0,0 +1,656 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.IO;
using PdfSharpCore.Pdf.Advanced;
using PdfSharpCore.Pdf.Security;
using PdfSharpCore.Pdf.Internal;
namespace PdfSharpCore.Pdf.IO
{
/// <summary>
/// Represents a writer for generation of PDF streams.
/// </summary>
internal class PdfWriter
{
public PdfWriter(Stream pdfStream, PdfStandardSecurityHandler securityHandler)
{
_stream = pdfStream;
_securityHandler = securityHandler;
//System.Xml.XmlTextWriter
// KillerPDF patch: never default to Verbose layout in DEBUG builds. Verbose sprinkles
// comments and loose token spacing through the output, which violates PDF/A object
// syntax rules (ISO 19005-1, 6.1.8) - a Debug-built KillerPDF must write the same
// conformant bytes a Release build writes.
}
public void Close(bool closeUnderlyingStream)
{
if (_stream != null && closeUnderlyingStream)
_stream.Dispose();
_stream = null;
}
public void Close()
{
Close(true);
}
public long Position
{
get { return _stream.Position; }
}
/// <summary>
/// Gets or sets the kind of layout.
/// </summary>
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);
// KillerPDF patch: bool.TrueString/FalseString are "True"/"False", which are NOT
// valid PDF boolean keywords (ISO 32000 7.3.2 requires lowercase). This corrupted
// indirect boolean objects (e.g. "42 0 obj True endobj") on resave.
WriteRaw(value ? "true" : "false");
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfBoolean value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.Value ? "true" : "false");
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(int value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.ToString(CultureInfo.InvariantCulture));
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(long value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.ToString(CultureInfo.InvariantCulture));
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(uint value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.ToString(CultureInfo.InvariantCulture));
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfInteger value)
{
WriteSeparator(CharCat.Character);
_lastCat = CharCat.Character;
WriteRaw(value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfLong value)
{
WriteSeparator(CharCat.Character);
_lastCat = CharCat.Character;
WriteRaw(value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfUInteger value)
{
WriteSeparator(CharCat.Character);
_lastCat = CharCat.Character;
WriteRaw(value.Value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(double value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.ToString(Config.SignificantFigures7, CultureInfo.InvariantCulture));
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfReal value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.Value.ToString(Config.SignificantFigures7, CultureInfo.InvariantCulture));
_lastCat = CharCat.Character;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfString value)
{
WriteSeparator(CharCat.Delimiter);
PdfStringEncoding encoding = (PdfStringEncoding)(value.Flags & PdfStringFlags.EncodingMask);
string pdf = (value.Flags & PdfStringFlags.HexLiteral) == 0 ?
PdfEncoders.ToStringLiteral(value.EncryptionValue, encoding == PdfStringEncoding.Unicode, SecurityHandler) :
PdfEncoders.ToHexStringLiteral(value.EncryptionValue, encoding == PdfStringEncoding.Unicode, SecurityHandler);
WriteRaw(pdf);
_lastCat = CharCat.Delimiter;
}
/// <summary>
/// Writes the specified value to the PDF stream.
/// </summary>
public void Write(PdfName value)
{
WriteSeparator(CharCat.Delimiter, '/');
string name = value.Value;
StringBuilder pdf = new StringBuilder("/");
for (int idx = 1; idx < name.Length; idx++)
{
char ch = name[idx];
Debug.Assert(ch < 256);
if (ch > ' ')
switch (ch)
{
// TODO: is this all?
case '%':
case '/':
case '<':
case '>':
case '(':
case ')':
case '#':
break;
default:
pdf.Append(name[idx]);
continue;
}
pdf.AppendFormat("#{0:X2}", (int)name[idx]);
}
WriteRaw(pdf.ToString());
_lastCat = CharCat.Character;
}
public void Write(PdfLiteral value)
{
WriteSeparator(CharCat.Character);
WriteRaw(value.Value);
_lastCat = CharCat.Character;
}
public void Write(PdfRectangle rect)
{
const string format = Config.SignificantFigures3;
WriteSeparator(CharCat.Delimiter, '/');
WriteRaw(PdfEncoders.Format("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", rect.X1, rect.Y1, rect.X2, rect.Y2));
_lastCat = CharCat.Delimiter;
}
public void Write(PdfReference iref)
{
WriteSeparator(CharCat.Character);
WriteRaw(iref.ToString());
_lastCat = CharCat.Character;
}
public void WriteDocString(string text, bool unicode)
{
WriteSeparator(CharCat.Delimiter);
//WriteRaw(PdfEncoders.DocEncode(text, unicode));
byte[] bytes;
if (!unicode)
bytes = PdfEncoders.DocEncoding.GetBytes(text);
else
bytes = PdfEncoders.UnicodeEncoding.GetBytes(text);
bytes = PdfEncoders.FormatStringLiteral(bytes, unicode, true, false, _securityHandler);
Write(bytes);
_lastCat = CharCat.Delimiter;
}
public void WriteDocString(string text)
{
WriteSeparator(CharCat.Delimiter);
//WriteRaw(PdfEncoders.DocEncode(text, false));
byte[] bytes = PdfEncoders.DocEncoding.GetBytes(text);
bytes = PdfEncoders.FormatStringLiteral(bytes, false, false, false, _securityHandler);
Write(bytes);
_lastCat = CharCat.Delimiter;
}
public void WriteDocStringHex(string text)
{
WriteSeparator(CharCat.Delimiter);
//WriteRaw(PdfEncoders.DocEncodeHex(text));
byte[] bytes = PdfEncoders.DocEncoding.GetBytes(text);
bytes = PdfEncoders.FormatStringLiteral(bytes, false, false, true, _securityHandler);
_stream.Write(bytes, 0, bytes.Length);
_lastCat = CharCat.Delimiter;
}
/// <summary>
/// Begins a direct or indirect dictionary or array.
/// </summary>
public void WriteBeginObject(PdfObject obj)
{
bool indirect = obj.IsIndirect;
if (indirect)
{
WriteObjectAddress(obj);
if (_securityHandler != null)
_securityHandler.SetHashKey(obj.ObjectID);
}
_stack.Add(new StackItem(obj));
if (indirect)
{
if (obj is PdfArray)
WriteRaw("[\n");
else if (obj is PdfDictionary)
WriteRaw("<<\n");
_lastCat = CharCat.NewLine;
}
else
{
if (obj is PdfArray)
{
WriteSeparator(CharCat.Delimiter);
WriteRaw('[');
_lastCat = CharCat.Delimiter;
}
else if (obj is PdfDictionary)
{
NewLine();
WriteSeparator(CharCat.Delimiter);
WriteRaw("<<\n");
_lastCat = CharCat.NewLine;
}
}
if (_layout == PdfWriterLayout.Verbose)
IncreaseIndent();
}
/// <summary>
/// Ends a direct or indirect dictionary or array.
/// </summary>
public void WriteEndObject()
{
int count = _stack.Count;
Debug.Assert(count > 0, "PdfWriter stack underflow.");
StackItem stackItem = _stack[count - 1];
_stack.RemoveAt(count - 1);
PdfObject value = stackItem.Object;
bool indirect = value.IsIndirect;
if (_layout == PdfWriterLayout.Verbose)
DecreaseIndent();
if (value is PdfArray)
{
if (indirect)
{
WriteRaw("\n]\n");
_lastCat = CharCat.NewLine;
}
else
{
WriteRaw("]");
_lastCat = CharCat.Delimiter;
}
}
else if (value is PdfDictionary)
{
if (indirect)
{
if (!stackItem.HasStream)
WriteRaw(_lastCat == CharCat.NewLine ? ">>\n" : " >>\n");
}
else
{
Debug.Assert(!stackItem.HasStream, "Direct object with stream??");
WriteSeparator(CharCat.NewLine);
WriteRaw(">>\n");
_lastCat = CharCat.NewLine;
}
}
if (indirect)
{
NewLine();
WriteRaw("endobj\n");
if (_layout == PdfWriterLayout.Verbose)
WriteRaw("%--------------------------------------------------------------------------------------------------\n");
}
}
/// <summary>
/// Writes the stream of the specified dictionary.
/// </summary>
public void WriteStream(PdfDictionary value, bool omitStream)
{
StackItem stackItem = _stack[_stack.Count - 1];
Debug.Assert(stackItem.Object is PdfDictionary);
Debug.Assert(stackItem.Object.IsIndirect);
stackItem.HasStream = true;
WriteRaw(_lastCat == CharCat.NewLine ? ">>\nstream\n" : " >>\nstream\n");
if (omitStream)
{
WriteRaw(" ...stream content omitted...\n"); // useful for debugging only
}
else
{
byte[] bytes = value.Stream.Value;
if (bytes.Length != 0)
{
if (_securityHandler != null)
{
bytes = (byte[])bytes.Clone();
bytes = _securityHandler.EncryptBytes(bytes);
}
Write(bytes);
}
// KillerPDF patch: ALWAYS write an explicit LF between the stream data and
// 'endstream' - INCLUDING for zero-length streams. The old conditional skipped
// it when the data ended in a newline byte (that byte then doubled as the EOL
// marker), and empty streams got no EOL at all ("stream\nendstream"), so /Length
// no longer matched ISO 19005's byte count (6.1.7: the bytes between the LF
// after 'stream' and the EOL before 'endstream'). The spec-blessed form is
// stream + LF + data + EOL + endstream, with both markers excluded from /Length;
// a compliant empty stream is "stream\n\nendstream".
WriteRaw('\n');
}
WriteRaw("endstream\n");
}
public void WriteRaw(string rawString)
{
if (String.IsNullOrEmpty(rawString))
return;
byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString);
_stream.Write(bytes, 0, bytes.Length);
_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);
}
public void Write(byte[] bytes)
{
if (bytes == null || bytes.Length == 0)
return;
_stream.Write(bytes, 0, bytes.Length);
_lastCat = GetCategory((char)bytes[bytes.Length - 1]);
}
void WriteObjectAddress(PdfObject value)
{
if (_layout == PdfWriterLayout.Verbose)
WriteRaw(String.Format("{0} {1} obj % {2}\n",
value.ObjectID.ObjectNumber, value.ObjectID.GenerationNumber,
value.GetType().FullName));
else
WriteRaw(String.Format("{0} {1} obj\n", value.ObjectID.ObjectNumber, value.ObjectID.GenerationNumber));
}
public void WriteFileHeader(PdfDocument document)
{
StringBuilder header = new StringBuilder("%PDF-");
int version = document._version;
header.Append((version / 10).ToString(CultureInfo.InvariantCulture) + "." +
(version % 10).ToString(CultureInfo.InvariantCulture) + "\n%\xD3\xF4\xCC\xE1\n");
WriteRaw(header.ToString());
if (_layout == PdfWriterLayout.Verbose)
{
WriteRaw(String.Format("% PDFsharp Version {0} (verbose mode)\n", VersionInfo.Version));
// Keep some space for later fix-up.
_commentPosition = (int)_stream.Position + 2;
WriteRaw("% \n");
WriteRaw("% \n");
WriteRaw("% \n");
WriteRaw("% \n");
WriteRaw("% \n");
WriteRaw("%--------------------------------------------------------------------------------------------------\n");
}
}
public void WriteEof(PdfDocument document, long startxref)
{
WriteRaw("startxref\n");
WriteRaw(startxref.ToString(CultureInfo.InvariantCulture));
WriteRaw("\n%%EOF\n");
var fileSize = _stream.Position;
if (_layout == PdfWriterLayout.Verbose)
{
TimeSpan duration = DateTime.Now - document._creation;
_stream.Position = _commentPosition;
// Without InvariantCulture parameter the following line fails if the current culture is e.g.
// a Far East culture, because the date string contains non-ASCII characters.
// So never never never never use ToString without a culture info.
WriteRaw("Creation date: " + document._creation.ToString("G", CultureInfo.InvariantCulture));
_stream.Position = _commentPosition + 50;
WriteRaw("Creation time: " + duration.TotalSeconds.ToString("0.000", CultureInfo.InvariantCulture) + " seconds");
_stream.Position = _commentPosition + 100;
WriteRaw("File size: " + fileSize.ToString(CultureInfo.InvariantCulture) + " bytes");
_stream.Position = _commentPosition + 150;
WriteRaw("Pages: " + document.Pages.Count.ToString(CultureInfo.InvariantCulture));
_stream.Position = _commentPosition + 200;
WriteRaw("Objects: " + document._irefTable.ObjectTable.Count.ToString(CultureInfo.InvariantCulture));
}
}
/// <summary>
/// Gets or sets the indentation for a new indentation level.
/// </summary>
internal int Indent
{
get { return _indent; }
set { _indent = value; }
}
int _indent = 2;
int _writeIndent;
/// <summary>
/// Increases indent level.
/// </summary>
void IncreaseIndent()
{
_writeIndent += _indent;
}
/// <summary>
/// Decreases indent level.
/// </summary>
void DecreaseIndent()
{
_writeIndent -= _indent;
}
///// <summary>
///// Returns an indent string of blanks.
///// </summary>
//static string Ind(int _indent)
//{
// return new String(' ', _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 (_layout == PdfWriterLayout.Verbose)
WriteIndent();
break;
case CharCat.Delimiter:
break;
case CharCat.Character:
if (_layout == PdfWriterLayout.Verbose)
{
//if (cat == CharCat.Character || ch == '/')
_stream.WriteByte((byte)' ');
}
else
{
//if (cat == CharCat.Character)
_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;
internal PdfStandardSecurityHandler SecurityHandler
{
get { return _securityHandler; }
set { _securityHandler = value; }
}
PdfStandardSecurityHandler _securityHandler;
class StackItem
{
public StackItem(PdfObject value)
{
Object = value;
}
public readonly PdfObject Object;
public bool HasStream;
}
readonly List<StackItem> _stack = new List<StackItem>();
int _commentPosition;
}
}
+142
View File
@@ -0,0 +1,142 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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.Collections.Generic;
using System.Diagnostics;
namespace PdfSharpCore.Pdf.IO
{
/// <summary>
/// Represents the stack for the shift-reduce parser. It seems that it is only needed for
/// reduction of indirect references.
/// </summary>
internal class ShiftStack
{
// TODO: make Lexer.PeekChars(20) and scan for 'R' to detect indirect references
public ShiftStack()
{
_items = new List<PdfItem>();
}
public PdfItem[] ToArray(int start, int length)
{
PdfItem[] items = new PdfItem[length];
for (int i = 0, j = start; i < length; i++, j++)
items[i] = _items[j];
return items;
}
/// <summary>
/// Gets the stack pointer index.
/// </summary>
// ReSharper disable InconsistentNaming
public int SP
// ReSharper restore InconsistentNaming
{
get { return _sp; }
}
/// <summary>
/// Gets the value at the specified index. Valid index is in range 0 up to sp-1.
/// </summary>
public PdfItem this[int index]
{
get
{
if (index >= _sp)
throw new ArgumentOutOfRangeException("index", index, "Value greater than stack index.");
return _items[index];
}
}
/// <summary>
/// Gets an item relative to the current stack pointer. The index must be a negative value (-1, -2, etc.).
/// </summary>
public PdfItem GetItem(int relativeIndex)
{
if (relativeIndex >= 0 || -relativeIndex > _sp)
throw new ArgumentOutOfRangeException("relativeIndex", relativeIndex, "Value out of stack range.");
return _items[_sp + relativeIndex];
}
/// <summary>
/// Gets an item relative to the current stack pointer. The index must be a negative value (-1, -2, etc.).
/// </summary>
public int GetInteger(int relativeIndex)
{
if (relativeIndex >= 0 || -relativeIndex > _sp)
throw new ArgumentOutOfRangeException("relativeIndex", relativeIndex, "Value out of stack range.");
return ((PdfInteger)_items[_sp + relativeIndex]).Value;
}
/// <summary>
/// Pushes the specified item onto the stack.
/// </summary>
public void Shift(PdfItem item)
{
Debug.Assert(item != null);
_items.Add(item);
_sp++;
}
/// <summary>
/// Replaces the last 'count' items with the specified item.
/// </summary>
public void Reduce(int count)
{
if (count > _sp)
throw new ArgumentException("count causes stack underflow.");
_items.RemoveRange(_sp - count, count);
_sp -= count;
}
/// <summary>
/// Replaces the last 'count' items with the specified item.
/// </summary>
public void Reduce(PdfItem item, int count)
{
Debug.Assert(item != null);
Reduce(count);
_items.Add(item);
_sp++;
}
/// <summary>
/// The stack pointer index. Points to the next free item.
/// </summary>
int _sp;
/// <summary>
/// An array representing the stack.
/// </summary>
readonly List<PdfItem> _items;
}
}
@@ -0,0 +1,52 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Determines the type of the password.
/// </summary>
public enum PasswordValidity
{
/// <summary>
/// Password is neither user nor owner password.
/// </summary>
Invalid,
/// <summary>
/// Password is user password.
/// </summary>
UserPassword,
/// <summary>
/// Password is owner password.
/// </summary>
OwnerPassword,
}
}
@@ -0,0 +1,63 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Determines how a PDF document is opened.
/// </summary>
public enum PdfDocumentOpenMode
{
/// <summary>
/// The PDF stream is completely read into memory and can be modified. Pages can be deleted or
/// inserted, but it is not possible to extract pages. This mode is useful for modifying an
/// existing PDF document.
/// </summary>
Modify,
/// <summary>
/// The PDF stream is opened for importing pages from it. A document opened in this mode cannot
/// be modified.
/// </summary>
Import,
/// <summary>
/// The PDF stream is completely read into memory, but cannot be modified. This mode preserves the
/// original internal structure of the document and is useful for analyzing existing PDF files.
/// </summary>
ReadOnly,
/// <summary>
/// The PDF stream is partially read for information purposes only. The only valid operation is to
/// call the Info property at the imported document. This option is very fast and needs less memory
/// and is e.g. useful for browsing information about a collection of PDF documents in a user interface.
/// </summary>
InformationOnly, // TODO: not yet implemented
}
}
@@ -0,0 +1,8 @@
namespace PdfSharpCore.Pdf.IO.enums
{
public enum PdfReadAccuracy
{
Strict,
Moderate
}
}
@@ -0,0 +1,61 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Determines how the PDF output stream is formatted. Even all formats create valid PDF files,
/// only Compact or Standard should be used for production purposes.
/// </summary>
public enum PdfWriterLayout
{
/// <summary>
/// The PDF stream contains no unnecessary characters. This is default in release build.
/// </summary>
Compact,
/// <summary>
/// The PDF stream contains some superfluous line feeds, but is more readable.
/// </summary>
Standard,
/// <summary>
/// The PDF stream is indented to reflect the nesting levels of the objects. This is useful
/// for analyzing PDF files, but increases the size of the file significantly.
/// </summary>
Indented,
/// <summary>
/// The PDF stream is indented to reflect the nesting levels of the objects and contains additional
/// information about the PDFsharp objects. Furthermore content streams are not deflated. This
/// is useful for debugging purposes only and increases the size of the file significantly.
/// </summary>
Verbose,
}
}
@@ -0,0 +1,56 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// INTERNAL USE ONLY.
/// </summary>
[Flags]
internal enum PdfWriterOptions
{
/// <summary>
/// If only this flag is specified the result is a regular valid PDF stream.
/// </summary>
Regular = 0x000000,
/// <summary>
/// Omit writing stream data. For debugging purposes only.
/// With this option the result is not valid PDF.
/// </summary>
OmitStream = 0x000001,
/// <summary>
/// Omit inflate filter. For debugging purposes only.
/// </summary>
OmitInflation = 0x000002,
}
}
+47
View File
@@ -0,0 +1,47 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany)
//
// http://www.PdfSharpCore.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 PdfSharpCore.Pdf.IO
{
/// <summary>
/// Terminal symbols recognized by lexer.
/// </summary>
public enum Symbol
{
#pragma warning disable 1591
None,
Comment, Null, Integer, UInteger, Real, Boolean, String, HexString, UnicodeString, UnicodeHexString,
Name, Keyword,
BeginStream, EndStream,
BeginArray, EndArray,
BeginDictionary, EndDictionary,
Obj, EndObj, R, XRef, Trailer, StartXRef, Eof, Long
#pragma warning restore 1591
}
}