1029 lines
41 KiB
C#
1029 lines
41 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 System.Globalization;
|
|||
|
using System.ComponentModel;
|
|||
|
using PdfSharp.Pdf.IO;
|
|||
|
using PdfSharp.Drawing;
|
|||
|
using PdfSharp.Pdf.Advanced;
|
|||
|
using PdfSharp.Pdf.Annotations;
|
|||
|
|
|||
|
namespace PdfSharp.Pdf
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Represents a page in a PDF document.
|
|||
|
/// </summary>
|
|||
|
public sealed class PdfPage : PdfDictionary, IContentStream
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Initializes a new page. The page must be added to a document before it can be used.
|
|||
|
/// Depending of the IsMetric property of the current region the page size is set to
|
|||
|
/// A4 or Letter respectively. If this size is not appropriate it should be changed before
|
|||
|
/// any drawing operations are performed on the page.
|
|||
|
/// </summary>
|
|||
|
public PdfPage()
|
|||
|
{
|
|||
|
Elements.SetName(Keys.Type, "/Page");
|
|||
|
Initialize();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes a new instance of the <see cref="PdfPage"/> class.
|
|||
|
/// </summary>
|
|||
|
/// <param name="document">The document.</param>
|
|||
|
public PdfPage(PdfDocument document)
|
|||
|
: base(document)
|
|||
|
{
|
|||
|
Elements.SetName(Keys.Type, "/Page");
|
|||
|
Elements[Keys.Parent] = document.Pages.Reference;
|
|||
|
Initialize();
|
|||
|
}
|
|||
|
|
|||
|
internal PdfPage(PdfDictionary dict)
|
|||
|
: base(dict)
|
|||
|
{
|
|||
|
// Set Orientation depending on /Rotate.
|
|||
|
|
|||
|
//!!!modTHHO 2016-06-16 Do not set Orientation here. Setting Orientation is not enough. Other properties must also be changed when setting Orientation.
|
|||
|
//!!!modTHHO 2018-04-05 Restored the old behavior. Commenting the next three lines out is not enough either.
|
|||
|
// New approach: remember that Orientation was set based on rotation.
|
|||
|
int rotate = Elements.GetInteger(InheritablePageKeys.Rotate);
|
|||
|
if (Math.Abs((rotate / 90)) % 2 == 1)
|
|||
|
{
|
|||
|
#if true
|
|||
|
_orientation = PageOrientation.Landscape;
|
|||
|
// Hacky approach: do not swap width and height on saving when orientation was set here.
|
|||
|
_orientationSetByCodeForRotatedDocument = true;
|
|||
|
#else
|
|||
|
// Cleaner approach: Swap width and height here. But some drawing routines will not draw the XPdfForm correctly, so this needs more testing and more changes.
|
|||
|
// When saving, width and height will be swapped. So we have to swap them here too.
|
|||
|
PdfRectangle mediaBox = MediaBox;
|
|||
|
MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void Initialize()
|
|||
|
{
|
|||
|
Size = RegionInfo.CurrentRegion.IsMetric ? PageSize.A4 : PageSize.Letter;
|
|||
|
|
|||
|
#pragma warning disable 168
|
|||
|
// Force creation of MediaBox object by invoking property.
|
|||
|
PdfRectangle rect = MediaBox;
|
|||
|
#pragma warning restore 168
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets a user defined object that contains arbitrary information associated with this PDF page.
|
|||
|
/// The tag is not used by PDFsharp.
|
|||
|
/// </summary>
|
|||
|
public object Tag
|
|||
|
{
|
|||
|
get { return _tag; }
|
|||
|
set { _tag = value; }
|
|||
|
}
|
|||
|
object _tag;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Closes the page. A closed page cannot be modified anymore and it is not possible to
|
|||
|
/// get an XGraphics object for a closed page. Closing a page is not required, but may save
|
|||
|
/// resources if the document has many pages.
|
|||
|
/// </summary>
|
|||
|
public void Close()
|
|||
|
{
|
|||
|
//// Close renderer, if any
|
|||
|
//if (_content.pdfRenderer != null)
|
|||
|
// _content.pdfRenderer.endp.Close();
|
|||
|
_closed = true;
|
|||
|
}
|
|||
|
bool _closed;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets a value indicating whether the page is closed.
|
|||
|
/// </summary>
|
|||
|
internal bool IsClosed
|
|||
|
{
|
|||
|
get { return _closed; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the PdfDocument this page belongs to.
|
|||
|
/// </summary>
|
|||
|
internal override PdfDocument Document
|
|||
|
{
|
|||
|
set
|
|||
|
{
|
|||
|
if (!ReferenceEquals(_document, value))
|
|||
|
{
|
|||
|
if (_document != null)
|
|||
|
throw new InvalidOperationException("Cannot change document.");
|
|||
|
_document = value;
|
|||
|
if (Reference != null)
|
|||
|
Reference.Document = value;
|
|||
|
Elements[Keys.Parent] = _document.Pages.Reference;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the orientation of the page. The default value PageOrientation.Portrait.
|
|||
|
/// If an imported page has a /Rotate value that matches the formula 90 + n * 180 the
|
|||
|
/// orientation is set to PageOrientation.Landscape.
|
|||
|
/// </summary>
|
|||
|
public PageOrientation Orientation
|
|||
|
{
|
|||
|
get { return _orientation; }
|
|||
|
set
|
|||
|
{
|
|||
|
_orientation = value;
|
|||
|
_orientationSetByCodeForRotatedDocument = false;
|
|||
|
}
|
|||
|
}
|
|||
|
PageOrientation _orientation;
|
|||
|
bool _orientationSetByCodeForRotatedDocument;
|
|||
|
// TODO Simplify the implementation. Should /Rotate 90 lead to Landscape format?
|
|||
|
// TODO Clean implementation without _orientationSetByCodeForRotatedDocument.
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets one of the predefined standard sizes like.
|
|||
|
/// </summary>
|
|||
|
public PageSize Size
|
|||
|
{
|
|||
|
get { return _pageSize; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (!Enum.IsDefined(typeof(PageSize), value))
|
|||
|
throw new InvalidEnumArgumentException("value", (int)value, typeof(PageSize));
|
|||
|
|
|||
|
XSize size = PageSizeConverter.ToSize(value);
|
|||
|
// MediaBox is always in Portrait mode (see Height, Width).
|
|||
|
// So take Orientation NOT into account.
|
|||
|
MediaBox = new PdfRectangle(0, 0, size.Width, size.Height);
|
|||
|
_pageSize = value;
|
|||
|
}
|
|||
|
}
|
|||
|
PageSize _pageSize;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the trim margins.
|
|||
|
/// </summary>
|
|||
|
public TrimMargins TrimMargins
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_trimMargins == null)
|
|||
|
_trimMargins = new TrimMargins();
|
|||
|
return _trimMargins;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (_trimMargins == null)
|
|||
|
_trimMargins = new TrimMargins();
|
|||
|
if (value != null)
|
|||
|
{
|
|||
|
_trimMargins.Left = value.Left;
|
|||
|
_trimMargins.Right = value.Right;
|
|||
|
_trimMargins.Top = value.Top;
|
|||
|
_trimMargins.Bottom = value.Bottom;
|
|||
|
}
|
|||
|
else
|
|||
|
_trimMargins.All = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
TrimMargins _trimMargins = new TrimMargins();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the media box directly. XGrahics is not prepared to work with a media box
|
|||
|
/// with an origin other than (0,0).
|
|||
|
/// </summary>
|
|||
|
public PdfRectangle MediaBox
|
|||
|
{
|
|||
|
get { return Elements.GetRectangle(Keys.MediaBox, true); }
|
|||
|
set { Elements.SetRectangle(Keys.MediaBox, value); }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the crop box.
|
|||
|
/// </summary>
|
|||
|
public PdfRectangle CropBox
|
|||
|
{
|
|||
|
get { return Elements.GetRectangle(Keys.CropBox, true); }
|
|||
|
set { Elements.SetRectangle(Keys.CropBox, value); }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the bleed box.
|
|||
|
/// </summary>
|
|||
|
public PdfRectangle BleedBox
|
|||
|
{
|
|||
|
get { return Elements.GetRectangle(Keys.BleedBox, true); }
|
|||
|
set { Elements.SetRectangle(Keys.BleedBox, value); }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the art box.
|
|||
|
/// </summary>
|
|||
|
public PdfRectangle ArtBox
|
|||
|
{
|
|||
|
get { return Elements.GetRectangle(Keys.ArtBox, true); }
|
|||
|
set { Elements.SetRectangle(Keys.ArtBox, value); }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the trim box.
|
|||
|
/// </summary>
|
|||
|
public PdfRectangle TrimBox
|
|||
|
{
|
|||
|
get { return Elements.GetRectangle(Keys.TrimBox, true); }
|
|||
|
set { Elements.SetRectangle(Keys.TrimBox, value); }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the height of the page. If orientation is Landscape, this function applies to
|
|||
|
/// the width.
|
|||
|
/// </summary>
|
|||
|
public XUnit Height
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
PdfRectangle rect = MediaBox;
|
|||
|
return _orientation == PageOrientation.Portrait ? rect.Height : rect.Width;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
PdfRectangle rect = MediaBox;
|
|||
|
if (_orientation == PageOrientation.Portrait)
|
|||
|
MediaBox = new PdfRectangle(rect.X1, 0, rect.X2, value);
|
|||
|
else
|
|||
|
MediaBox = new PdfRectangle(0, rect.Y1, value, rect.Y2);
|
|||
|
_pageSize = PageSize.Undefined;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the width of the page. If orientation is Landscape, this function applies to
|
|||
|
/// the height.
|
|||
|
/// </summary>
|
|||
|
public XUnit Width
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
PdfRectangle rect = MediaBox;
|
|||
|
return _orientation == PageOrientation.Portrait ? rect.Width : rect.Height;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
PdfRectangle rect = MediaBox;
|
|||
|
if (_orientation == PageOrientation.Portrait)
|
|||
|
MediaBox = new PdfRectangle(0, rect.Y1, value, rect.Y2);
|
|||
|
else
|
|||
|
MediaBox = new PdfRectangle(rect.X1, 0, rect.X2, value);
|
|||
|
_pageSize = PageSize.Undefined;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the /Rotate entry of the PDF page. The value is the number of degrees by which the page
|
|||
|
/// should be rotated clockwise when displayed or printed. The value must be a multiple of 90.
|
|||
|
/// PDFsharp does not set this value, but for imported pages this value can be set and must be taken
|
|||
|
/// into account when adding graphic to such a page.
|
|||
|
/// </summary>
|
|||
|
public int Rotate
|
|||
|
{
|
|||
|
get { return _elements.GetInteger(InheritablePageKeys.Rotate); }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value % 90 != 0)
|
|||
|
throw new ArgumentException("Value must be a multiple of 90.");
|
|||
|
_elements.SetInteger(InheritablePageKeys.Rotate, value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// TODO: PdfAnnotations
|
|||
|
// TODO: PdfActions
|
|||
|
// TODO: PdfPageTransition
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The content stream currently used by an XGraphics object for rendering.
|
|||
|
/// </summary>
|
|||
|
internal PdfContent RenderContent;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the array of content streams of the page.
|
|||
|
/// </summary>
|
|||
|
public PdfContents Contents
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_contents == null)
|
|||
|
{
|
|||
|
if (true) // || Document.IsImported)
|
|||
|
{
|
|||
|
PdfItem item = Elements[Keys.Contents];
|
|||
|
if (item == null)
|
|||
|
{
|
|||
|
_contents = new PdfContents(Owner);
|
|||
|
//Owner.irefTable.Add(_contents);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (item is PdfReference)
|
|||
|
item = ((PdfReference)item).Value;
|
|||
|
|
|||
|
PdfArray array = item as PdfArray;
|
|||
|
if (array != null)
|
|||
|
{
|
|||
|
// It is already an array of content streams.
|
|||
|
if (array.IsIndirect)
|
|||
|
{
|
|||
|
// Make it a direct array
|
|||
|
array = array.Clone();
|
|||
|
array.Document = Owner;
|
|||
|
}
|
|||
|
// TODO 4STLA: Causes Exception "Object type transformation must not be done with direct objects" in "protected PdfObject(PdfObject obj)"
|
|||
|
_contents = new PdfContents(array);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Only one content stream -> create array
|
|||
|
_contents = new PdfContents(Owner);
|
|||
|
//Owner.irefTable.Add(_contents);
|
|||
|
PdfContent content = new PdfContent((PdfDictionary)item);
|
|||
|
_contents.Elements.Add(content.Reference);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//else
|
|||
|
//{
|
|||
|
// _content = new PdfContent(Document);
|
|||
|
// Document.xrefTable.Add(_content);
|
|||
|
//}
|
|||
|
Debug.Assert(_contents.Reference == null);
|
|||
|
Elements[Keys.Contents] = _contents;
|
|||
|
}
|
|||
|
return _contents;
|
|||
|
}
|
|||
|
}
|
|||
|
PdfContents _contents;
|
|||
|
|
|||
|
#region Annotations
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the annotations array of this page.
|
|||
|
/// </summary>
|
|||
|
public bool HasAnnotations
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_annotations == null)
|
|||
|
{
|
|||
|
// Get annotations array if exists.
|
|||
|
_annotations = (PdfAnnotations)Elements.GetValue(Keys.Annots);
|
|||
|
_annotations.Page = this;
|
|||
|
}
|
|||
|
return _annotations != null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the annotations array of this page.
|
|||
|
/// </summary>
|
|||
|
public PdfAnnotations Annotations
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_annotations == null)
|
|||
|
{
|
|||
|
// Get or create annotations array.
|
|||
|
_annotations = (PdfAnnotations)Elements.GetValue(Keys.Annots, VCF.Create);
|
|||
|
_annotations.Page = this;
|
|||
|
}
|
|||
|
return _annotations;
|
|||
|
}
|
|||
|
}
|
|||
|
PdfAnnotations _annotations;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Adds an intra document link.
|
|||
|
/// </summary>
|
|||
|
/// <param name="rect">The rect.</param>
|
|||
|
/// <param name="destinationPage">The destination page.</param>
|
|||
|
public PdfLinkAnnotation AddDocumentLink(PdfRectangle rect, int destinationPage)
|
|||
|
{
|
|||
|
PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateDocumentLink(rect, destinationPage);
|
|||
|
Annotations.Add(annotation);
|
|||
|
return annotation;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Adds a link to the Web.
|
|||
|
/// </summary>
|
|||
|
/// <param name="rect">The rect.</param>
|
|||
|
/// <param name="url">The URL.</param>
|
|||
|
public PdfLinkAnnotation AddWebLink(PdfRectangle rect, string url)
|
|||
|
{
|
|||
|
PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateWebLink(rect, url);
|
|||
|
Annotations.Add(annotation);
|
|||
|
return annotation;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Adds a link to a file.
|
|||
|
/// </summary>
|
|||
|
/// <param name="rect">The rect.</param>
|
|||
|
/// <param name="fileName">Name of the file.</param>
|
|||
|
public PdfLinkAnnotation AddFileLink(PdfRectangle rect, string fileName)
|
|||
|
{
|
|||
|
PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateFileLink(rect, fileName);
|
|||
|
Annotations.Add(annotation);
|
|||
|
return annotation;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the custom values.
|
|||
|
/// </summary>
|
|||
|
public PdfCustomValues CustomValues
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_customValues == null)
|
|||
|
_customValues = PdfCustomValues.Get(Elements);
|
|||
|
return _customValues;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != null)
|
|||
|
throw new ArgumentException("Only null is allowed to clear all custom values.");
|
|||
|
PdfCustomValues.Remove(Elements);
|
|||
|
_customValues = null;
|
|||
|
}
|
|||
|
}
|
|||
|
PdfCustomValues _customValues;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the PdfResources object of this page.
|
|||
|
/// </summary>
|
|||
|
public PdfResources Resources
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_resources == null)
|
|||
|
_resources = (PdfResources)Elements.GetValue(Keys.Resources, VCF.Create); //VCF.CreateIndirect
|
|||
|
return _resources;
|
|||
|
}
|
|||
|
}
|
|||
|
PdfResources _resources;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Implements the interface because the primary function is internal.
|
|||
|
/// </summary>
|
|||
|
PdfResources IContentStream.Resources
|
|||
|
{
|
|||
|
get { return Resources; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the resource name of the specified font within this page.
|
|||
|
/// </summary>
|
|||
|
internal string GetFontName(XFont font, out PdfFont pdfFont)
|
|||
|
{
|
|||
|
pdfFont = _document.FontTable.GetFont(font);
|
|||
|
Debug.Assert(pdfFont != null);
|
|||
|
string name = Resources.AddFont(pdfFont);
|
|||
|
return name;
|
|||
|
}
|
|||
|
|
|||
|
string IContentStream.GetFontName(XFont font, out PdfFont pdfFont)
|
|||
|
{
|
|||
|
return GetFontName(font, out pdfFont);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Tries to get the resource name of the specified font data within this page.
|
|||
|
/// Returns null if no such font exists.
|
|||
|
/// </summary>
|
|||
|
internal string TryGetFontName(string idName, out PdfFont pdfFont)
|
|||
|
{
|
|||
|
pdfFont = _document.FontTable.TryGetFont(idName);
|
|||
|
string name = null;
|
|||
|
if (pdfFont != null)
|
|||
|
name = Resources.AddFont(pdfFont);
|
|||
|
return name;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the resource name of the specified font data within this page.
|
|||
|
/// </summary>
|
|||
|
internal string GetFontName(string idName, byte[] fontData, out PdfFont pdfFont)
|
|||
|
{
|
|||
|
pdfFont = _document.FontTable.GetFont(idName, fontData);
|
|||
|
//pdfFont = new PdfType0Font(Owner, idName, fontData);
|
|||
|
//pdfFont.Document = _document;
|
|||
|
Debug.Assert(pdfFont != null);
|
|||
|
string name = Resources.AddFont(pdfFont);
|
|||
|
return name;
|
|||
|
}
|
|||
|
|
|||
|
string IContentStream.GetFontName(string idName, byte[] fontData, out PdfFont pdfFont)
|
|||
|
{
|
|||
|
return GetFontName(idName, fontData, out pdfFont);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the resource name of the specified image within this page.
|
|||
|
/// </summary>
|
|||
|
internal string GetImageName(XImage image)
|
|||
|
{
|
|||
|
PdfImage pdfImage = _document.ImageTable.GetImage(image);
|
|||
|
Debug.Assert(pdfImage != null);
|
|||
|
string name = Resources.AddImage(pdfImage);
|
|||
|
return name;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Implements the interface because the primary function is internal.
|
|||
|
/// </summary>
|
|||
|
string IContentStream.GetImageName(XImage image)
|
|||
|
{
|
|||
|
return GetImageName(image);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the resource name of the specified form within this page.
|
|||
|
/// </summary>
|
|||
|
internal string GetFormName(XForm form)
|
|||
|
{
|
|||
|
PdfFormXObject pdfForm = _document.FormTable.GetForm(form);
|
|||
|
Debug.Assert(pdfForm != null);
|
|||
|
string name = Resources.AddForm(pdfForm);
|
|||
|
return name;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Implements the interface because the primary function is internal.
|
|||
|
/// </summary>
|
|||
|
string IContentStream.GetFormName(XForm form)
|
|||
|
{
|
|||
|
return GetFormName(form);
|
|||
|
}
|
|||
|
|
|||
|
internal override void WriteObject(PdfWriter writer)
|
|||
|
{
|
|||
|
// HACK: temporarily flip media box if Landscape
|
|||
|
PdfRectangle mediaBox = MediaBox;
|
|||
|
// TODO: Take /Rotate into account
|
|||
|
//!!!newTHHO 2018-04-05 Stop manipulating the MediaBox - Height and Width properties already take orientation into account.
|
|||
|
//!!!delTHHO 2018-04-05 if (_orientation == PageOrientation.Landscape)
|
|||
|
//!!!delTHHO 2018-04-05 MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2);
|
|||
|
// One step back - swap members in MediaBox for landscape orientation.
|
|||
|
if (_orientation == PageOrientation.Landscape && !_orientationSetByCodeForRotatedDocument)
|
|||
|
MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2);
|
|||
|
|
|||
|
#if true
|
|||
|
// Add transparency group to prevent rendering problems of Adobe viewer.
|
|||
|
// Update (PDFsharp 1.50 beta 3): Add transparency group only if ColorMode is defined.
|
|||
|
// Rgb is the default for the ColorMode, but if user sets it to Undefined then
|
|||
|
// we respect this and skip the transparency group.
|
|||
|
TransparencyUsed = true; // TODO: check XObjects
|
|||
|
if (TransparencyUsed && !Elements.ContainsKey(Keys.Group) &&
|
|||
|
_document.Options.ColorMode != PdfColorMode.Undefined)
|
|||
|
{
|
|||
|
PdfDictionary group = new PdfDictionary();
|
|||
|
_elements["/Group"] = group;
|
|||
|
if (_document.Options.ColorMode != PdfColorMode.Cmyk)
|
|||
|
group.Elements.SetName("/CS", "/DeviceRGB");
|
|||
|
else
|
|||
|
group.Elements.SetName("/CS", "/DeviceCMYK");
|
|||
|
group.Elements.SetName("/S", "/Transparency");
|
|||
|
//False is default: group.Elements["/I"] = new PdfBoolean(false);
|
|||
|
//False is default: group.Elements["/K"] = new PdfBoolean(false);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if DEBUG_
|
|||
|
PdfItem item = Elements["/MediaBox"];
|
|||
|
if (item != null)
|
|||
|
item.GetType();
|
|||
|
#endif
|
|||
|
base.WriteObject(writer);
|
|||
|
|
|||
|
//!!!delTHHO 2018-04-05 if (_orientation == PageOrientation.Landscape)
|
|||
|
//!!!delTHHO 2018-04-05 MediaBox = mediaBox;
|
|||
|
// One step back - swap members in MediaBox for landscape orientation.
|
|||
|
if (_orientation == PageOrientation.Landscape && !_orientationSetByCodeForRotatedDocument)
|
|||
|
MediaBox = mediaBox;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Hack to indicate that a page-level transparency group must be created.
|
|||
|
/// </summary>
|
|||
|
internal bool TransparencyUsed;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Inherit values from parent node.
|
|||
|
/// </summary>
|
|||
|
internal static void InheritValues(PdfDictionary page, InheritedValues values)
|
|||
|
{
|
|||
|
// HACK: I'M ABSOLUTELY NOT SURE WHETHER THIS CODE COVERS ALL CASES.
|
|||
|
if (values.Resources != null)
|
|||
|
{
|
|||
|
PdfDictionary resources;
|
|||
|
PdfItem res = page.Elements[InheritablePageKeys.Resources];
|
|||
|
if (res is PdfReference)
|
|||
|
{
|
|||
|
resources = (PdfDictionary)((PdfReference)res).Value.Clone();
|
|||
|
resources.Document = page.Owner;
|
|||
|
}
|
|||
|
else
|
|||
|
resources = (PdfDictionary)res;
|
|||
|
|
|||
|
if (resources == null)
|
|||
|
{
|
|||
|
resources = values.Resources.Clone();
|
|||
|
resources.Document = page.Owner;
|
|||
|
page.Elements.Add(InheritablePageKeys.Resources, resources);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
foreach (PdfName name in values.Resources.Elements.KeyNames)
|
|||
|
{
|
|||
|
if (!resources.Elements.ContainsKey(name.Value))
|
|||
|
{
|
|||
|
PdfItem item = values.Resources.Elements[name];
|
|||
|
if (item is PdfObject)
|
|||
|
item = item.Clone();
|
|||
|
resources.Elements.Add(name.ToString(), item);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (values.MediaBox != null && page.Elements[InheritablePageKeys.MediaBox] == null)
|
|||
|
page.Elements[InheritablePageKeys.MediaBox] = values.MediaBox;
|
|||
|
|
|||
|
if (values.CropBox != null && page.Elements[InheritablePageKeys.CropBox] == null)
|
|||
|
page.Elements[InheritablePageKeys.CropBox] = values.CropBox;
|
|||
|
|
|||
|
if (values.Rotate != null && page.Elements[InheritablePageKeys.Rotate] == null)
|
|||
|
page.Elements[InheritablePageKeys.Rotate] = values.Rotate;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Add all inheritable values from the specified page to the specified values structure.
|
|||
|
/// </summary>
|
|||
|
internal static void InheritValues(PdfDictionary page, ref InheritedValues values)
|
|||
|
{
|
|||
|
PdfItem item = page.Elements[InheritablePageKeys.Resources];
|
|||
|
if (item != null)
|
|||
|
{
|
|||
|
PdfReference reference = item as PdfReference;
|
|||
|
if (reference != null)
|
|||
|
values.Resources = (PdfDictionary)(reference.Value);
|
|||
|
else
|
|||
|
values.Resources = (PdfDictionary)item;
|
|||
|
}
|
|||
|
|
|||
|
item = page.Elements[InheritablePageKeys.MediaBox];
|
|||
|
if (item != null)
|
|||
|
values.MediaBox = new PdfRectangle(item);
|
|||
|
|
|||
|
item = page.Elements[InheritablePageKeys.CropBox];
|
|||
|
if (item != null)
|
|||
|
values.CropBox = new PdfRectangle(item);
|
|||
|
|
|||
|
item = page.Elements[InheritablePageKeys.Rotate];
|
|||
|
if (item != null)
|
|||
|
{
|
|||
|
if (item is PdfReference)
|
|||
|
item = ((PdfReference)item).Value;
|
|||
|
values.Rotate = (PdfInteger)item;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal override void PrepareForSave()
|
|||
|
{
|
|||
|
if (_trimMargins.AreSet)
|
|||
|
{
|
|||
|
// These are the values InDesign set for an A4 page with 3mm crop margin at each edge.
|
|||
|
// (recall that PDF rect are two points and NOT a point and a width)
|
|||
|
// /MediaBox[0.0 0.0 612.283 858.898] 216 302.7
|
|||
|
// /CropBox[0.0 0.0 612.283 858.898]
|
|||
|
// /BleedBox[0.0 0.0 612.283 858.898]
|
|||
|
// /ArtBox[8.50394 8.50394 603.78 850.394] 3 3 213 300
|
|||
|
// /TrimBox[8.50394 8.50394 603.78 850.394]
|
|||
|
|
|||
|
double width = _trimMargins.Left.Point + Width.Point + _trimMargins.Right.Point;
|
|||
|
double height = _trimMargins.Top.Point + Height.Point + _trimMargins.Bottom.Point;
|
|||
|
|
|||
|
MediaBox = new PdfRectangle(0, 0, width, height);
|
|||
|
CropBox = new PdfRectangle(0, 0, width, height);
|
|||
|
BleedBox = new PdfRectangle(0, 0, width, height);
|
|||
|
|
|||
|
PdfRectangle rect = new PdfRectangle(_trimMargins.Left.Point, _trimMargins.Top.Point,
|
|||
|
width - _trimMargins.Right.Point, height - _trimMargins.Bottom.Point);
|
|||
|
TrimBox = rect;
|
|||
|
ArtBox = rect.Clone();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Predefined keys of this dictionary.
|
|||
|
/// </summary>
|
|||
|
internal sealed class Keys : InheritablePageKeys
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// (Required) The type of PDF object that this dictionary describes;
|
|||
|
/// must be Page for a page object.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Page")]
|
|||
|
public const string Type = "/Type";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Required; must be an indirect reference)
|
|||
|
/// The page tree node that is the immediate parent of this page object.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Dictionary | KeyType.Required | KeyType.MustBeIndirect)]
|
|||
|
public const string Parent = "/Parent";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Required if PieceInfo is present; optional otherwise; PDF 1.3) The date and time
|
|||
|
/// when the page<67>s contents were most recently modified. If a page-piece dictionary
|
|||
|
/// (PieceInfo) is present, the modification date is used to ascertain which of the
|
|||
|
/// application data dictionaries that it contains correspond to the current content
|
|||
|
/// of the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Date)]
|
|||
|
public const string LastModified = "/LastModified";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A rectangle, expressed in default user space units, defining the
|
|||
|
/// region to which the contents of the page should be clipped when output in a production
|
|||
|
/// environment. Default value: the value of CropBox.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)]
|
|||
|
public const string BleedBox = "/BleedBox";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A rectangle, expressed in default user space units, defining the
|
|||
|
/// intended dimensions of the finished page after trimming. Default value: the value of
|
|||
|
/// CropBox.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)]
|
|||
|
public const string TrimBox = "/TrimBox";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A rectangle, expressed in default user space units, defining the
|
|||
|
/// extent of the page<67>s meaningful content (including potential white space) as intended
|
|||
|
/// by the page<67>s creator. Default value: the value of CropBox.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)]
|
|||
|
public const string ArtBox = "/ArtBox";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.4) A box color information dictionary specifying the colors and other
|
|||
|
/// visual characteristics to be used in displaying guidelines on the screen for the various
|
|||
|
/// page boundaries. If this entry is absent, the application should use its own current
|
|||
|
/// default settings.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string BoxColorInfo = "/BoxColorInfo";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional) A content stream describing the contents of this page. If this entry is absent,
|
|||
|
/// the page is empty. The value may be either a single stream or an array of streams. If the
|
|||
|
/// value is an array, the effect is as if all of the streams in the array were concatenated,
|
|||
|
/// in order, to form a single stream. This allows PDF producers to create image objects and
|
|||
|
/// other resources as they occur, even though they interrupt the content stream. The division
|
|||
|
/// between streams may occur only at the boundaries between lexical tokens but is unrelated
|
|||
|
/// to the page<67>s logical content or organization. Applications that consume or produce PDF
|
|||
|
/// files are not required to preserve the existing structure of the Contents array.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Array | KeyType.Stream | KeyType.Optional)]
|
|||
|
public const string Contents = "/Contents";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.4) A group attributes dictionary specifying the attributes of the page<67>s
|
|||
|
/// page group for use in the transparent imaging model.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string Group = "/Group";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional) A stream object defining the page<67>s thumbnail image.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Stream | KeyType.Optional)]
|
|||
|
public const string Thumb = "/Thumb";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.1; recommended if the page contains article beads) An array of indirect
|
|||
|
/// references to article beads appearing on the page. The beads are listed in the array in
|
|||
|
/// natural reading order.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.1", KeyType.Array | KeyType.Optional)]
|
|||
|
public const string B = "/B";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.1) The page<67>s display duration (also called its advance timing): the
|
|||
|
/// maximum length of time, in seconds, that the page is displayed during presentations before
|
|||
|
/// the viewer application automatically advances to the next page. By default, the viewer does
|
|||
|
/// not advance automatically.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.1", KeyType.Real | KeyType.Optional)]
|
|||
|
public const string Dur = "/Dur";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.1) A transition dictionary describing the transition effect to be used
|
|||
|
/// when displaying the page during presentations.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.1", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string Trans = "/Trans";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional) An array of annotation dictionaries representing annotations associated with
|
|||
|
/// the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Array | KeyType.Optional, typeof(PdfAnnotations))]
|
|||
|
public const string Annots = "/Annots";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.2) An additional-actions dictionary defining actions to be performed
|
|||
|
/// when the page is opened or closed.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.2", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string AA = "/AA";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.4) A metadata stream containing metadata for the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.4", KeyType.Stream | KeyType.Optional)]
|
|||
|
public const string Metadata = "/Metadata";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A page-piece dictionary associated with the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string PieceInfo = "/PieceInfo";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Required if the page contains structural content items; PDF 1.3)
|
|||
|
/// The integer key of the page<67>s entry in the structural parent tree.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Integer | KeyType.Optional)]
|
|||
|
public const string StructParents = "/StructParents";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3; indirect reference preferred) The digital identifier of
|
|||
|
/// the page<67>s parent Web Capture content set.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.String | KeyType.Optional)]
|
|||
|
public const string ID = "/ID";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) The page<67>s preferred zoom (magnification) factor: the factor
|
|||
|
/// by which it should be scaled to achieve the natural display magnification.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Real | KeyType.Optional)]
|
|||
|
public const string PZ = "/PZ";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A separation dictionary containing information needed
|
|||
|
/// to generate color separations for the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string SeparationInfo = "/SeparationInfo";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.5) A name specifying the tab order to be used for annotations
|
|||
|
/// on the page. The possible values are R (row order), C (column order),
|
|||
|
/// and S (structure order).
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.5", KeyType.Name | KeyType.Optional)]
|
|||
|
public const string Tabs = "/Tabs";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Required if this page was created from a named page object; PDF 1.5)
|
|||
|
/// The name of the originating page object.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Name | KeyType.Optional)]
|
|||
|
public const string TemplateInstantiated = "/TemplateInstantiated";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.5) A navigation node dictionary representing the first node
|
|||
|
/// on the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.5", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string PresSteps = "/PresSteps";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.6) A positive number giving the size of default user space units,
|
|||
|
/// in multiples of 1/72 inch. The range of supported values is implementation-dependent.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.6", KeyType.Real | KeyType.Optional)]
|
|||
|
public const string UserUnit = "/UserUnit";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.6) An array of viewport dictionaries specifying rectangular regions
|
|||
|
/// of the page.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.6", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string VP = "/VP";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets the KeysMeta for these keys.
|
|||
|
/// </summary>
|
|||
|
internal 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; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Predefined keys common to PdfPage and PdfPages.
|
|||
|
/// </summary>
|
|||
|
internal class InheritablePageKeys : KeysBase
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// (Required; inheritable) A dictionary containing any resources required by the page.
|
|||
|
/// If the page requires no resources, the value of this entry should be an empty dictionary.
|
|||
|
/// Omitting the entry entirely indicates that the resources are to be inherited from an
|
|||
|
/// ancestor node in the page tree.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Dictionary | KeyType.Required | KeyType.Inheritable, typeof(PdfResources))]
|
|||
|
public const string Resources = "/Resources";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Required; inheritable) A rectangle, expressed in default user space units, defining the
|
|||
|
/// boundaries of the physical medium on which the page is intended to be displayed or printed.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Rectangle | KeyType.Required | KeyType.Inheritable)]
|
|||
|
public const string MediaBox = "/MediaBox";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; inheritable) A rectangle, expressed in default user space units, defining the
|
|||
|
/// visible region of default user space. When the page is displayed or printed, its contents
|
|||
|
/// are to be clipped (cropped) to this rectangle and then imposed on the output medium in some
|
|||
|
/// implementation defined manner. Default value: the value of MediaBox.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Rectangle | KeyType.Optional | KeyType.Inheritable)]
|
|||
|
public const string CropBox = "/CropBox";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; inheritable) The number of degrees by which the page should be rotated clockwise
|
|||
|
/// when displayed or printed. The value must be a multiple of 90. Default value: 0.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.Integer | KeyType.Optional)]
|
|||
|
public const string Rotate = "/Rotate";
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Values inherited from a parent in the parent chain of a page tree.
|
|||
|
/// </summary>
|
|||
|
internal struct InheritedValues
|
|||
|
{
|
|||
|
public PdfDictionary Resources;
|
|||
|
public PdfRectangle MediaBox;
|
|||
|
public PdfRectangle CropBox;
|
|||
|
public PdfInteger Rotate;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|