193 lines
7.0 KiB
C#
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; }
|
|
}
|
|
}
|
|
}
|