ASCU_ALL/PdfSharp/Pdf.Advanced/PdfContent.cs
2020-09-04 12:49:15 +05:00

193 lines
7.0 KiB
C#

#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Diagnostics;
using PdfSharp.Drawing.Pdf;
using PdfSharp.Pdf.Filters;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents the content of a page. PDFsharp supports only one content stream per page.
/// If an imported page has an array of content streams, the streams are concatenated to
/// one single stream.
/// </summary>
public sealed class PdfContent : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfContent"/> class.
/// </summary>
public PdfContent(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="PdfContent"/> class.
/// </summary>
internal PdfContent(PdfPage page)
: base(page != null ? page.Owner : null)
{
//_pageContent = new PageContent(page);
}
/// <summary>
/// Initializes a new instance of the <see cref="PdfContent"/> class.
/// </summary>
/// <param name="dict">The dict.</param>
public PdfContent(PdfDictionary dict) // HACK PdfContent
: base(dict)
{
// A PdfContent dictionary is always unfiltered.
Decode();
}
/// <summary>
/// Sets a value indicating whether the content is compressed with the ZIP algorithm.
/// </summary>
public bool Compressed
{
set
{
if (value)
{
PdfItem filter = Elements["/Filter"];
if (filter == null)
{
byte[] bytes = Filtering.FlateDecode.Encode(Stream.Value, _document.Options.FlateEncodeMode);
Stream.Value = bytes;
Elements.SetInteger("/Length", Stream.Length);
Elements.SetName("/Filter", "/FlateDecode");
}
}
}
}
/// <summary>
/// Unfilters the stream.
/// </summary>
void Decode()
{
if (Stream != null && Stream.Value != null)
{
PdfItem item = Elements["/Filter"];
if (item != null)
{
byte[] bytes = Filtering.Decode(Stream.Value, item);
if (bytes != null)
{
Stream.Value = bytes;
Elements.Remove("/Filter");
Elements.SetInteger("/Length", Stream.Length);
}
}
}
}
/// <summary>
/// Surround content with q/Q operations if necessary.
/// </summary>
internal void PreserveGraphicsState()
{
// If a content stream is touched by PDFsharp it is typically because graphical operations are
// prepended or appended. Some nasty PDF tools does not preserve the graphical state correctly.
// Therefore we try to relieve the problem by surrounding the content stream with push/restore
// graphic state operation.
if (Stream != null)
{
byte[] value = Stream.Value;
int length = value.Length;
if (length != 0 && ((value[0] != (byte)'q' || value[1] != (byte)'\n')))
{
byte[] newValue = new byte[length + 2 + 3];
newValue[0] = (byte)'q';
newValue[1] = (byte)'\n';
Array.Copy(value, 0, newValue, 2, length);
newValue[length + 2] = (byte)' ';
newValue[length + 3] = (byte)'Q';
newValue[length + 4] = (byte)'\n';
Stream.Value = newValue;
Elements.SetInteger("/Length", Stream.Length);
}
}
}
internal override void WriteObject(PdfWriter writer)
{
if (_pdfRenderer != null)
{
// GetContent also disposes the underlying XGraphics object, if one exists
//Stream = new PdfStream(PdfEncoders.RawEncoding.GetBytes(pdfRenderer.GetContent()), this);
_pdfRenderer.Close();
Debug.Assert(_pdfRenderer == null);
}
if (Stream != null)
{
//if (Owner.Options.CompressContentStreams)
if (Owner.Options.CompressContentStreams && Elements.GetName("/Filter").Length == 0)
{
Stream.Value = Filtering.FlateDecode.Encode(Stream.Value, _document.Options.FlateEncodeMode);
//Elements["/Filter"] = new PdfName("/FlateDecode");
Elements.SetName("/Filter", "/FlateDecode");
}
Elements.SetInteger("/Length", Stream.Length);
}
base.WriteObject(writer);
}
internal XGraphicsPdfRenderer _pdfRenderer;
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
internal sealed class Keys : PdfStream.Keys
{
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
public static DictionaryMeta Meta
{
get { return _meta ?? (_meta = CreateMeta(typeof(Keys))); }
}
static DictionaryMeta _meta;
}
/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}