First commit

Send all results
This commit is contained in:
2020-09-04 12:49:15 +05:00
commit 330a2ccfda
2819 changed files with 226201 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
#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.Filters
{
/// <summary>
/// Implements the ASCII85Decode filter.
/// </summary>
public class Ascii85Decode : Filter
{
// Reference: 3.3.2 ASCII85Decode Filter / Page 69
/// <summary>
/// Encodes the specified data.
/// </summary>
public override byte[] Encode(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
int length = data.Length; // length == 0 is must not be treated as a special case.
int words = length / 4;
int rest = length - (words * 4);
byte[] result = new byte[words * 5 + (rest == 0 ? 0 : rest + 1) + 2];
int idxIn = 0, idxOut = 0;
int wCount = 0;
while (wCount < words)
{
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn++] << 16) + ((uint)data[idxIn++] << 8) + data[idxIn++];
if (val == 0)
{
result[idxOut++] = (byte)'z';
}
else
{
byte c5 = (byte)(val % 85 + '!');
val /= 85;
byte c4 = (byte)(val % 85 + '!');
val /= 85;
byte c3 = (byte)(val % 85 + '!');
val /= 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
result[idxOut++] = c1;
result[idxOut++] = c2;
result[idxOut++] = c3;
result[idxOut++] = c4;
result[idxOut++] = c5;
}
wCount++;
}
if (rest == 1)
{
uint val = (uint)data[idxIn] << 24;
val /= 85 * 85 * 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
result[idxOut++] = c1;
result[idxOut++] = c2;
}
else if (rest == 2)
{
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn] << 16);
val /= 85 * 85;
byte c3 = (byte)(val % 85 + '!');
val /= 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
result[idxOut++] = c1;
result[idxOut++] = c2;
result[idxOut++] = c3;
}
else if (rest == 3)
{
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn++] << 16) + ((uint)data[idxIn] << 8);
val /= 85;
byte c4 = (byte)(val % 85 + '!');
val /= 85;
byte c3 = (byte)(val % 85 + '!');
val /= 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
result[idxOut++] = c1;
result[idxOut++] = c2;
result[idxOut++] = c3;
result[idxOut++] = c4;
}
result[idxOut++] = (byte)'~';
result[idxOut++] = (byte)'>';
if (idxOut < result.Length)
Array.Resize(ref result, idxOut);
return result;
}
/// <summary>
/// Decodes the specified data.
/// </summary>
public override byte[] Decode(byte[] data, FilterParms parms)
{
if (data == null)
throw new ArgumentNullException("data");
int idx;
int length = data.Length;
int zCount = 0;
int idxOut = 0;
for (idx = 0; idx < length; idx++)
{
char ch = (char)data[idx];
if (ch >= '!' && ch <= 'u')
data[idxOut++] = (byte)ch;
else if (ch == 'z')
{
data[idxOut++] = (byte)ch;
zCount++;
}
else if (ch == '~')
{
if ((char)data[idx + 1] != '>')
throw new ArgumentException("Illegal character.", "data");
break;
}
// ingnore unknown character
}
// Loop not ended with break?
if (idx == length)
throw new ArgumentException("Illegal character.", "data");
length = idxOut;
int nonZero = length - zCount;
int byteCount = 4 * (zCount + (nonZero / 5)); // full 4 byte blocks
int remainder = nonZero % 5;
if (remainder == 1)
throw new InvalidOperationException("Illegal character.");
if (remainder != 0)
byteCount += remainder - 1;
byte[] output = new byte[byteCount];
idxOut = 0;
idx = 0;
while (idx + 4 < length)
{
char ch = (char)data[idx];
if (ch == 'z')
{
idx++;
idxOut += 4;
}
else
{
// TODO: check
long value =
(long)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
(uint)(data[idx++] - '!') * (85 * 85) +
(uint)(data[idx++] - '!') * 85 +
(uint)(data[idx++] - '!');
if (value > UInt32.MaxValue)
throw new InvalidOperationException("Value of group greater than 2 power 32 - 1.");
output[idxOut++] = (byte)(value >> 24);
output[idxOut++] = (byte)(value >> 16);
output[idxOut++] = (byte)(value >> 8);
output[idxOut++] = (byte)value;
}
}
// I have found no appropriate algorithm, so I write my own. In some rare cases the value must not
// increased by one, but I cannot found a general formula or a proof.
// All possible cases are tested programmatically.
if (remainder == 2) // one byte
{
uint value =
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
(uint)(data[idx] - '!') * (85 * 85 * 85);
// Always increase if not zero (tried out).
if (value != 0)
value += 0x01000000;
output[idxOut] = (byte)(value >> 24);
}
else if (remainder == 3) // two bytes
{
int idxIn = idx;
uint value =
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
(uint)(data[idx] - '!') * (85 * 85);
if (value != 0)
{
value &= 0xFFFF0000;
uint val = value / (85 * 85);
byte c3 = (byte)(val % 85 + '!');
val /= 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
if (c1 != data[idxIn] || c2 != data[idxIn + 1] || c3 != data[idxIn + 2])
{
value += 0x00010000;
//Count2++;
}
}
output[idxOut++] = (byte)(value >> 24);
output[idxOut] = (byte)(value >> 16);
}
else if (remainder == 4) // three bytes
{
int idxIn = idx;
uint value =
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
(uint)(data[idx++] - '!') * (85 * 85) +
(uint)(data[idx] - '!') * 85;
if (value != 0)
{
value &= 0xFFFFFF00;
uint val = value / 85;
byte c4 = (byte)(val % 85 + '!');
val /= 85;
byte c3 = (byte)(val % 85 + '!');
val /= 85;
byte c2 = (byte)(val % 85 + '!');
val /= 85;
byte c1 = (byte)(val + '!');
if (c1 != data[idxIn] || c2 != data[idxIn + 1] || c3 != data[idxIn + 2] || c4 != data[idxIn + 3])
{
value += 0x00000100;
//Count3++;
}
}
output[idxOut++] = (byte)(value >> 24);
output[idxOut++] = (byte)(value >> 16);
output[idxOut] = (byte)(value >> 8);
}
return output;
}
}
}

View File

@@ -0,0 +1,98 @@
#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.Filters
{
/// <summary>
/// Implements the ASCIIHexDecode filter.
/// </summary>
public class AsciiHexDecode : Filter
{
// Reference: 3.3.1 ASCIIHexDecode Filter / Page 69
/// <summary>
/// Encodes the specified data.
/// </summary>
public override byte[] Encode(byte[] data)
{
if (data == null)
throw new ArgumentNullException("data");
int count = data.Length;
byte[] bytes = new byte[2 * count];
for (int i = 0, j = 0; i < count; i++)
{
byte b = data[i];
bytes[j++] = (byte)((b >> 4) + ((b >> 4) < 10 ? (byte)'0' : (byte)('A' - 10)));
bytes[j++] = (byte)((b & 0xF) + ((b & 0xF) < 10 ? (byte)'0' : (byte)('A' - 10)));
}
return bytes;
}
/// <summary>
/// Decodes the specified data.
/// </summary>
public override byte[] Decode(byte[] data, FilterParms parms)
{
if (data == null)
throw new ArgumentNullException("data");
data = RemoveWhiteSpace(data);
int count = data.Length;
// Ignore EOD (end of data) character.
// EOD can be anywhere in the stream, but makes sense only at the end of the stream.
if (count > 0 && data[count - 1] == '>')
--count;
if (count % 2 == 1)
{
count++;
byte[] temp = data;
data = new byte[count];
temp.CopyTo(data, 0);
}
count >>= 1;
byte[] bytes = new byte[count];
for (int i = 0, j = 0; i < count; i++)
{
// Must support 0-9, A-F, a-f - "Any other characters cause an error."
byte hi = data[j++];
byte lo = data[j++];
if (hi >= 'a' && hi <= 'f')
hi -= 32;
if (lo >= 'a' && lo <= 'f')
lo -= 32;
// TODO Throw on invalid characters. Stop when encountering EOD. Add one more byte if EOD is the lo byte.
bytes[i] = (byte)((hi > '9' ? hi - '7'/*'A' + 10*/: hi - '0') * 16 + (lo > '9' ? lo - '7'/*'A' + 10*/: lo - '0'));
}
return bytes;
}
}
}

View File

@@ -0,0 +1,130 @@
#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 PdfSharp.Pdf.IO;
using PdfSharp.Pdf.Internal;
namespace PdfSharp.Pdf.Filters
{
/// <summary>
/// Reserved for future extension.
/// </summary>
public class FilterParms
{
// not yet used
}
/// <summary>
/// Base class for all stream filters
/// </summary>
public abstract class Filter
{
/// <summary>
/// When implemented in a derived class encodes the specified data.
/// </summary>
public abstract byte[] Encode(byte[] data);
/// <summary>
/// Encodes a raw string.
/// </summary>
public virtual byte[] Encode(string rawString)
{
byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString);
bytes = Encode(bytes);
return bytes;
}
/// <summary>
/// When implemented in a derived class decodes the specified data.
/// </summary>
public abstract byte[] Decode(byte[] data, FilterParms parms);
/// <summary>
/// Decodes the specified data.
/// </summary>
public byte[] Decode(byte[] data)
{
return Decode(data, null);
}
/// <summary>
/// Decodes to a raw string.
/// </summary>
public virtual string DecodeToString(byte[] data, FilterParms parms)
{
byte[] bytes = Decode(data, parms);
string text = PdfEncoders.RawEncoding.GetString(bytes, 0, bytes.Length);
return text;
}
/// <summary>
/// Decodes to a raw string.
/// </summary>
public string DecodeToString(byte[] data)
{
return DecodeToString(data, null);
}
/// <summary>
/// Removes all white spaces from the data. The function assumes that the bytes are characters.
/// </summary>
protected byte[] RemoveWhiteSpace(byte[] data)
{
int count = data.Length;
int j = 0;
for (int i = 0; i < count; i++, j++)
{
switch (data[i])
{
case (byte)Chars.NUL: // 0 Null
case (byte)Chars.HT: // 9 Tab
case (byte)Chars.LF: // 10 Line feed
case (byte)Chars.FF: // 12 Form feed
case (byte)Chars.CR: // 13 Carriage return
case (byte)Chars.SP: // 32 Space
j--;
break;
default:
if (i != j)
data[j] = data[i];
break;
}
}
if (j < count)
{
byte[] temp = data;
data = new byte[j];
for (int idx = 0; idx < j; idx++)
data[idx] = temp[idx];
}
return data;
}
}
}

View File

@@ -0,0 +1,242 @@
#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;
namespace PdfSharp.Pdf.Filters
{
/// <summary>
/// Applies standard filters to streams.
/// </summary>
public static class Filtering
{
/// <summary>
/// Gets the filter specified by the case sensitive name.
/// </summary>
public static Filter GetFilter(string filterName)
{
if (filterName.StartsWith("/"))
filterName = filterName.Substring(1);
// Some tools use abbreviations
switch (filterName)
{
case "ASCIIHexDecode":
case "AHx":
return _asciiHexDecode ?? (_asciiHexDecode = new AsciiHexDecode());
case "ASCII85Decode":
case "A85":
return _ascii85Decode ?? (_ascii85Decode = new Ascii85Decode());
case "LZWDecode":
case "LZW":
return _lzwDecode ?? (_lzwDecode = new LzwDecode());
case "FlateDecode":
case "Fl":
return _flateDecode ?? (_flateDecode = new FlateDecode());
//case "RunLengthDecode":
// if (RunLengthDecode == null)
// RunLengthDecode = new RunLengthDecode();
// return RunLengthDecode;
//
//case "CCITTFaxDecode":
// if (CCITTFaxDecode == null)
// CCITTFaxDecode = new CCITTFaxDecode();
// return CCITTFaxDecode;
//
//case "JBIG2Decode":
// if (JBIG2Decode == null)
// JBIG2Decode = new JBIG2Decode();
// return JBIG2Decode;
//
//case "DCTDecode":
// if (DCTDecode == null)
// DCTDecode = new DCTDecode();
// return DCTDecode;
//
//case "JPXDecode":
// if (JPXDecode == null)
// JPXDecode = new JPXDecode();
// return JPXDecode;
//
//case "Crypt":
// if (Crypt == null)
// Crypt = new Crypt();
// return Crypt;
case "RunLengthDecode":
case "CCITTFaxDecode":
case "JBIG2Decode":
case "DCTDecode":
case "JPXDecode":
case "Crypt":
Debug.WriteLine("Filter not implemented: " + filterName);
return null;
}
throw new NotImplementedException("Unknown filter: " + filterName);
}
/// <summary>
/// Gets the filter singleton.
/// </summary>
// ReSharper disable InconsistentNaming
public static AsciiHexDecode ASCIIHexDecode
// ReSharper restore InconsistentNaming
{
get { return _asciiHexDecode ?? (_asciiHexDecode = new AsciiHexDecode()); }
}
static AsciiHexDecode _asciiHexDecode;
/// <summary>
/// Gets the filter singleton.
/// </summary>
public static Ascii85Decode ASCII85Decode
{
get { return _ascii85Decode ?? (_ascii85Decode = new Ascii85Decode()); }
}
static Ascii85Decode _ascii85Decode;
/// <summary>
/// Gets the filter singleton.
/// </summary>
public static LzwDecode LzwDecode
{
get { return _lzwDecode ?? (_lzwDecode = new LzwDecode()); }
}
static LzwDecode _lzwDecode;
/// <summary>
/// Gets the filter singleton.
/// </summary>
public static FlateDecode FlateDecode
{
get { return _flateDecode ?? (_flateDecode = new FlateDecode()); }
}
static FlateDecode _flateDecode;
//runLengthDecode
//ccittFaxDecode
//jbig2Decode
//dctDecode
//jpxDecode
//crypt
/// <summary>
/// Encodes the data with the specified filter.
/// </summary>
public static byte[] Encode(byte[] data, string filterName)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.Encode(data);
return null;
}
/// <summary>
/// Encodes a raw string with the specified filter.
/// </summary>
public static byte[] Encode(string rawString, string filterName)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.Encode(rawString);
return null;
}
/// <summary>
/// Decodes the data with the specified filter.
/// </summary>
public static byte[] Decode(byte[] data, string filterName, FilterParms parms)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.Decode(data, parms);
return null;
}
/// <summary>
/// Decodes the data with the specified filter.
/// </summary>
public static byte[] Decode(byte[] data, string filterName)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.Decode(data, null);
return null;
}
/// <summary>
/// Decodes the data with the specified filter.
/// </summary>
public static byte[] Decode(byte[] data, PdfItem filterItem)
{
byte[] result = null;
if (filterItem is PdfName)
{
Filter filter = GetFilter(filterItem.ToString());
if (filter != null)
result = filter.Decode(data);
}
else if (filterItem is PdfArray)
{
PdfArray array = (PdfArray)filterItem;
foreach (PdfItem item in array)
data = Decode(data, item);
result = data;
}
return result;
}
/// <summary>
/// Decodes to a raw string with the specified filter.
/// </summary>
public static string DecodeToString(byte[] data, string filterName, FilterParms parms)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.DecodeToString(data, parms);
return null;
}
/// <summary>
/// Decodes to a raw string with the specified filter.
/// </summary>
public static string DecodeToString(byte[] data, string filterName)
{
Filter filter = GetFilter(filterName);
if (filter != null)
return filter.DecodeToString(data, null);
return null;
}
}
}

View File

@@ -0,0 +1,220 @@
#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.IO;
using PdfSharp.Internal;
#if NET_ZIP
using System.IO.Compression;
#else
using PdfSharp.SharpZipLib.Zip.Compression;
using PdfSharp.SharpZipLib.Zip.Compression.Streams;
#endif
namespace PdfSharp.Pdf.Filters
{
/// <summary>
/// Implements the FlateDecode filter by wrapping SharpZipLib.
/// </summary>
public class FlateDecode : Filter
{
// Reference: 3.3.3 LZWDecode and FlateDecode Filters / Page 71
/// <summary>
/// Encodes the specified data.
/// </summary>
public override byte[] Encode(byte[] data)
{
return Encode(data, PdfFlateEncodeMode.Default);
}
/// <summary>
/// Encodes the specified data.
/// </summary>
public byte[] Encode(byte[] data, PdfFlateEncodeMode mode)
{
MemoryStream ms = new MemoryStream();
// DeflateStream/GZipStream does not work immediately and I have not the leisure to work it out.
// So I keep on using SharpZipLib even with .NET 2.0.
#if NET_ZIP
// See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97064
//
// Excerpt from the RFC 1950 specs for first byte:
//
// CMF (Compression Method and flags)
// This byte is divided into a 4-bit compression method and a 4-
// bit information field depending on the compression method.
//
// bits 0 to 3 CM Compression method
// bits 4 to 7 CINFO Compression info
//
// CM (Compression method)
// This identifies the compression method used in the file. CM = 8
// denotes the "deflate" compression method with a window size up
// to 32K. This is the method used by gzip and PNG (see
// references [1] and [2] in Chapter 3, below, for the reference
// documents). CM = 15 is reserved. It might be used in a future
// version of this specification to indicate the presence of an
// extra field before the compressed data.
//
// CINFO (Compression info)
// For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
// size, minus eight (CINFO=7 indicates a 32K window size). Values
// of CINFO above 7 are not allowed in this version of the
// specification. CINFO is not defined in this specification for
// CM not equal to 8.
ms.WriteByte(0x78);
// Excerpt from the RFC 1950 specs for second byte:
//
// FLG (FLaGs)
// This flag byte is divided as follows:
//
// bits 0 to 4 FCHECK (check bits for CMF and FLG)
// bit 5 FDICT (preset dictionary)
// bits 6 to 7 FLEVEL (compression level)
//
// The FCHECK value must be such that CMF and FLG, when viewed as
// a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
// is a multiple of 31.
//
// FDICT (Preset dictionary)
// If FDICT is set, a DICT dictionary identifier is present
// immediately after the FLG byte. The dictionary is a sequence of
// bytes which are initially fed to the compressor without
// producing any compressed output. DICT is the Adler-32 checksum
// of this sequence of bytes (see the definition of ADLER32
// below). The decompressor can use this identifier to determine
// which dictionary has been used by the compressor.
//
// FLEVEL (Compression level)
// These flags are available for use by specific compression
// methods. The "deflate" method (CM = 8) sets these flags as
// follows:
//
// 0 - compressor used fastest algorithm
// 1 - compressor used fast algorithm
// 2 - compressor used default algorithm
// 3 - compressor used maximum compression, slowest algorithm
//
// The information in FLEVEL is not needed for decompression; it
// is there to indicate if recompression might be worthwhile.
ms.WriteByte(0x49);
DeflateStream zip = new DeflateStream(ms, CompressionMode.Compress, true);
zip.Write(data, 0, data.Length);
zip.Close();
#else
int level = Deflater.DEFAULT_COMPRESSION;
switch (mode)
{
case PdfFlateEncodeMode.BestCompression:
level = Deflater.BEST_COMPRESSION;
break;
case PdfFlateEncodeMode.BestSpeed:
level = Deflater.BEST_SPEED;
break;
}
DeflaterOutputStream zip = new DeflaterOutputStream(ms, new Deflater(level, false));
zip.Write(data, 0, data.Length);
zip.Finish();
#endif
#if !NETFX_CORE && !UWP
ms.Capacity = (int)ms.Length;
return ms.GetBuffer();
#else
return ms.ToArray();
#endif
}
/// <summary>
/// Decodes the specified data.
/// </summary>
public override byte[] Decode(byte[] data, FilterParms parms)
{
MemoryStream msInput = new MemoryStream(data);
MemoryStream msOutput = new MemoryStream();
#if NET_ZIP
// See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97064
// It seems to work when skipping the first two bytes.
byte header; // 0x30 0x59
header = (byte)msInput.ReadByte();
//Debug.Assert(header == 48);
header = (byte)msInput.ReadByte();
//Debug.Assert(header == 89);
DeflateStream zip = new DeflateStream(msInput, CompressionMode.Decompress, true);
int cbRead;
byte[] abResult = new byte[1024];
do
{
cbRead = zip.Read(abResult, 0, abResult.Length);
if (cbRead > 0)
msOutput.Write(abResult, 0, cbRead);
}
while (cbRead > 0);
zip.Close();
msOutput.Flush();
if (msOutput.Length >= 0)
{
msOutput.Capacity = (int)msOutput.Length;
return msOutput.GetBuffer();
}
return null;
#else
InflaterInputStream iis = new InflaterInputStream(msInput, new Inflater(false));
int cbRead;
byte[] abResult = new byte[32768];
do
{
cbRead = iis.Read(abResult, 0, abResult.Length);
if (cbRead > 0)
msOutput.Write(abResult, 0, cbRead);
}
while (cbRead > 0);
#if UWP
iis.Dispose();
#else
iis.Close();
#endif
msOutput.Flush();
if (msOutput.Length >= 0)
{
#if NETFX_CORE || UWP
return msOutput.ToArray();
#else
msOutput.Capacity = (int)msOutput.Length;
return msOutput.GetBuffer();
#endif
}
return null;
#endif
}
}
}

View File

@@ -0,0 +1,189 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// David Stephensen
//
// 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.IO;
namespace PdfSharp.Pdf.Filters
{
/// <summary>
/// Implements the LzwDecode filter.
/// </summary>
public class LzwDecode : Filter
{
// Reference: 3.3.3 LZWDecode and FlateDecode Filters / Page 71
/// <summary>
/// Throws a NotImplementedException because the obsolete LZW encoding is not supported by PDFsharp.
/// </summary>
public override byte[] Encode(byte[] data)
{
throw new NotImplementedException("PDFsharp does not support LZW encoding.");
}
/// <summary>
/// Decodes the specified data.
/// </summary>
public override byte[] Decode(byte[] data, FilterParms parms)
{
if (data[0] == 0x00 && data[1] == 0x01)
throw new Exception("LZW flavour not supported.");
MemoryStream outputStream = new MemoryStream();
InitializeDictionary();
_data = data;
_bytePointer = 0;
_nextData = 0;
_nextBits = 0;
int code, oldCode = 0;
byte[] str;
while ((code = NextCode) != 257)
{
if (code == 256)
{
InitializeDictionary();
code = NextCode;
if (code == 257)
{
break;
}
outputStream.Write(_stringTable[code], 0, _stringTable[code].Length);
oldCode = code;
}
else
{
if (code < _tableIndex)
{
str = _stringTable[code];
outputStream.Write(str, 0, str.Length);
AddEntry(_stringTable[oldCode], str[0]);
oldCode = code;
}
else
{
str = _stringTable[oldCode];
outputStream.Write(str, 0, str.Length);
AddEntry(str, str[0]);
oldCode = code;
}
}
}
if (outputStream.Length >= 0)
{
#if !NETFX_CORE && !UWP
outputStream.Capacity = (int)outputStream.Length;
return outputStream.GetBuffer();
#else
return outputStream.ToArray();
#endif
}
return null;
}
/// <summary>
/// Initialize the dictionary.
/// </summary>
void InitializeDictionary()
{
_stringTable = new byte[8192][];
for (int i = 0; i < 256; i++)
{
_stringTable[i] = new byte[1];
_stringTable[i][0] = (byte)i;
}
_tableIndex = 258;
_bitsToGet = 9;
}
/// <summary>
/// Add a new entry to the Dictionary.
/// </summary>
void AddEntry(byte[] oldstring, byte newstring)
{
int length = oldstring.Length;
byte[] str = new byte[length + 1];
Array.Copy(oldstring, 0, str, 0, length);
str[length] = newstring;
_stringTable[_tableIndex++] = str;
if (_tableIndex == 511)
_bitsToGet = 10;
else if (_tableIndex == 1023)
_bitsToGet = 11;
else if (_tableIndex == 2047)
_bitsToGet = 12;
}
/// <summary>
/// Returns the next set of bits.
/// </summary>
int NextCode
{
get
{
try
{
_nextData = (_nextData << 8) | (_data[_bytePointer++] & 0xff);
_nextBits += 8;
if (_nextBits < _bitsToGet)
{
_nextData = (_nextData << 8) | (_data[_bytePointer++] & 0xff);
_nextBits += 8;
}
int code = (_nextData >> (_nextBits - _bitsToGet)) & _andTable[_bitsToGet - 9];
_nextBits -= _bitsToGet;
return code;
}
catch
{
return 257;
}
}
}
readonly int[] _andTable = { 511, 1023, 2047, 4095 };
byte[][] _stringTable;
byte[] _data;
int _tableIndex, _bitsToGet = 9;
int _bytePointer;
int _nextData = 0;
int _nextBits = 0;
}
}