#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 { /// /// Represents a page in a PDF document. /// public sealed class PdfPage : PdfDictionary, IContentStream { /// /// 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. /// public PdfPage() { Elements.SetName(Keys.Type, "/Page"); Initialize(); } /// /// Initializes a new instance of the class. /// /// The document. 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 } /// /// Gets or sets a user defined object that contains arbitrary information associated with this PDF page. /// The tag is not used by PDFsharp. /// public object Tag { get { return _tag; } set { _tag = value; } } object _tag; /// /// 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. /// public void Close() { //// Close renderer, if any //if (_content.pdfRenderer != null) // _content.pdfRenderer.endp.Close(); _closed = true; } bool _closed; /// /// Gets a value indicating whether the page is closed. /// internal bool IsClosed { get { return _closed; } } /// /// Gets or sets the PdfDocument this page belongs to. /// 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; } } } /// /// 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. /// 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. /// /// Gets or sets one of the predefined standard sizes like. /// 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; /// /// Gets or sets the trim margins. /// 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(); /// /// Gets or sets the media box directly. XGrahics is not prepared to work with a media box /// with an origin other than (0,0). /// public PdfRectangle MediaBox { get { return Elements.GetRectangle(Keys.MediaBox, true); } set { Elements.SetRectangle(Keys.MediaBox, value); } } /// /// Gets or sets the crop box. /// public PdfRectangle CropBox { get { return Elements.GetRectangle(Keys.CropBox, true); } set { Elements.SetRectangle(Keys.CropBox, value); } } /// /// Gets or sets the bleed box. /// public PdfRectangle BleedBox { get { return Elements.GetRectangle(Keys.BleedBox, true); } set { Elements.SetRectangle(Keys.BleedBox, value); } } /// /// Gets or sets the art box. /// public PdfRectangle ArtBox { get { return Elements.GetRectangle(Keys.ArtBox, true); } set { Elements.SetRectangle(Keys.ArtBox, value); } } /// /// Gets or sets the trim box. /// public PdfRectangle TrimBox { get { return Elements.GetRectangle(Keys.TrimBox, true); } set { Elements.SetRectangle(Keys.TrimBox, value); } } /// /// Gets or sets the height of the page. If orientation is Landscape, this function applies to /// the width. /// 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; } } /// /// Gets or sets the width of the page. If orientation is Landscape, this function applies to /// the height. /// 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; } } /// /// 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. /// 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 /// /// The content stream currently used by an XGraphics object for rendering. /// internal PdfContent RenderContent; /// /// Gets the array of content streams of the page. /// 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 /// /// Gets the annotations array of this page. /// public bool HasAnnotations { get { if (_annotations == null) { // Get annotations array if exists. _annotations = (PdfAnnotations)Elements.GetValue(Keys.Annots); _annotations.Page = this; } return _annotations != null; } } /// /// Gets the annotations array of this page. /// 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; /// /// Adds an intra document link. /// /// The rect. /// The destination page. public PdfLinkAnnotation AddDocumentLink(PdfRectangle rect, int destinationPage) { PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateDocumentLink(rect, destinationPage); Annotations.Add(annotation); return annotation; } /// /// Adds a link to the Web. /// /// The rect. /// The URL. public PdfLinkAnnotation AddWebLink(PdfRectangle rect, string url) { PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateWebLink(rect, url); Annotations.Add(annotation); return annotation; } /// /// Adds a link to a file. /// /// The rect. /// Name of the file. public PdfLinkAnnotation AddFileLink(PdfRectangle rect, string fileName) { PdfLinkAnnotation annotation = PdfLinkAnnotation.CreateFileLink(rect, fileName); Annotations.Add(annotation); return annotation; } #endregion /// /// Gets or sets the custom values. /// 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; /// /// Gets the PdfResources object of this page. /// public PdfResources Resources { get { if (_resources == null) _resources = (PdfResources)Elements.GetValue(Keys.Resources, VCF.Create); //VCF.CreateIndirect return _resources; } } PdfResources _resources; /// /// Implements the interface because the primary function is internal. /// PdfResources IContentStream.Resources { get { return Resources; } } /// /// Gets the resource name of the specified font within this page. /// 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); } /// /// Tries to get the resource name of the specified font data within this page. /// Returns null if no such font exists. /// 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; } /// /// Gets the resource name of the specified font data within this page. /// 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); } /// /// Gets the resource name of the specified image within this page. /// internal string GetImageName(XImage image) { PdfImage pdfImage = _document.ImageTable.GetImage(image); Debug.Assert(pdfImage != null); string name = Resources.AddImage(pdfImage); return name; } /// /// Implements the interface because the primary function is internal. /// string IContentStream.GetImageName(XImage image) { return GetImageName(image); } /// /// Gets the resource name of the specified form within this page. /// internal string GetFormName(XForm form) { PdfFormXObject pdfForm = _document.FormTable.GetForm(form); Debug.Assert(pdfForm != null); string name = Resources.AddForm(pdfForm); return name; } /// /// Implements the interface because the primary function is internal. /// 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; } /// /// Hack to indicate that a page-level transparency group must be created. /// internal bool TransparencyUsed; /// /// Inherit values from parent node. /// 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; } /// /// Add all inheritable values from the specified page to the specified values structure. /// 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(); } } /// /// Predefined keys of this dictionary. /// internal sealed class Keys : InheritablePageKeys { /// /// (Required) The type of PDF object that this dictionary describes; /// must be Page for a page object. /// [KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Page")] public const string Type = "/Type"; /// /// (Required; must be an indirect reference) /// The page tree node that is the immediate parent of this page object. /// [KeyInfo(KeyType.Dictionary | KeyType.Required | KeyType.MustBeIndirect)] public const string Parent = "/Parent"; /// /// (Required if PieceInfo is present; optional otherwise; PDF 1.3) The date and time /// when the page’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. /// [KeyInfo(KeyType.Date)] public const string LastModified = "/LastModified"; /// /// (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. /// [KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)] public const string BleedBox = "/BleedBox"; /// /// (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. /// [KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)] public const string TrimBox = "/TrimBox"; /// /// (Optional; PDF 1.3) A rectangle, expressed in default user space units, defining the /// extent of the page’s meaningful content (including potential white space) as intended /// by the page’s creator. Default value: the value of CropBox. /// [KeyInfo("1.3", KeyType.Rectangle | KeyType.Optional)] public const string ArtBox = "/ArtBox"; /// /// (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. /// [KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)] public const string BoxColorInfo = "/BoxColorInfo"; /// /// (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’s logical content or organization. Applications that consume or produce PDF /// files are not required to preserve the existing structure of the Contents array. /// [KeyInfo(KeyType.Array | KeyType.Stream | KeyType.Optional)] public const string Contents = "/Contents"; /// /// (Optional; PDF 1.4) A group attributes dictionary specifying the attributes of the page’s /// page group for use in the transparent imaging model. /// [KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)] public const string Group = "/Group"; /// /// (Optional) A stream object defining the page’s thumbnail image. /// [KeyInfo(KeyType.Stream | KeyType.Optional)] public const string Thumb = "/Thumb"; /// /// (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. /// [KeyInfo("1.1", KeyType.Array | KeyType.Optional)] public const string B = "/B"; /// /// (Optional; PDF 1.1) The page’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. /// [KeyInfo("1.1", KeyType.Real | KeyType.Optional)] public const string Dur = "/Dur"; /// /// (Optional; PDF 1.1) A transition dictionary describing the transition effect to be used /// when displaying the page during presentations. /// [KeyInfo("1.1", KeyType.Dictionary | KeyType.Optional)] public const string Trans = "/Trans"; /// /// (Optional) An array of annotation dictionaries representing annotations associated with /// the page. /// [KeyInfo(KeyType.Array | KeyType.Optional, typeof(PdfAnnotations))] public const string Annots = "/Annots"; /// /// (Optional; PDF 1.2) An additional-actions dictionary defining actions to be performed /// when the page is opened or closed. /// [KeyInfo("1.2", KeyType.Dictionary | KeyType.Optional)] public const string AA = "/AA"; /// /// (Optional; PDF 1.4) A metadata stream containing metadata for the page. /// [KeyInfo("1.4", KeyType.Stream | KeyType.Optional)] public const string Metadata = "/Metadata"; /// /// (Optional; PDF 1.3) A page-piece dictionary associated with the page. /// [KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)] public const string PieceInfo = "/PieceInfo"; /// /// (Required if the page contains structural content items; PDF 1.3) /// The integer key of the page’s entry in the structural parent tree. /// [KeyInfo(KeyType.Integer | KeyType.Optional)] public const string StructParents = "/StructParents"; /// /// (Optional; PDF 1.3; indirect reference preferred) The digital identifier of /// the page’s parent Web Capture content set. /// [KeyInfo("1.3", KeyType.String | KeyType.Optional)] public const string ID = "/ID"; /// /// (Optional; PDF 1.3) The page’s preferred zoom (magnification) factor: the factor /// by which it should be scaled to achieve the natural display magnification. /// [KeyInfo("1.3", KeyType.Real | KeyType.Optional)] public const string PZ = "/PZ"; /// /// (Optional; PDF 1.3) A separation dictionary containing information needed /// to generate color separations for the page. /// [KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)] public const string SeparationInfo = "/SeparationInfo"; /// /// (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). /// [KeyInfo("1.5", KeyType.Name | KeyType.Optional)] public const string Tabs = "/Tabs"; /// /// (Required if this page was created from a named page object; PDF 1.5) /// The name of the originating page object. /// [KeyInfo(KeyType.Name | KeyType.Optional)] public const string TemplateInstantiated = "/TemplateInstantiated"; /// /// (Optional; PDF 1.5) A navigation node dictionary representing the first node /// on the page. /// [KeyInfo("1.5", KeyType.Dictionary | KeyType.Optional)] public const string PresSteps = "/PresSteps"; /// /// (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. /// [KeyInfo("1.6", KeyType.Real | KeyType.Optional)] public const string UserUnit = "/UserUnit"; /// /// (Optional; PDF 1.6) An array of viewport dictionaries specifying rectangular regions /// of the page. /// [KeyInfo("1.6", KeyType.Dictionary | KeyType.Optional)] public const string VP = "/VP"; /// /// Gets the KeysMeta for these keys. /// internal static DictionaryMeta Meta { get { return _meta ?? (_meta = CreateMeta(typeof(Keys))); } } static DictionaryMeta _meta; } /// /// Gets the KeysMeta of this dictionary type. /// internal override DictionaryMeta Meta { get { return Keys.Meta; } } /// /// Predefined keys common to PdfPage and PdfPages. /// internal class InheritablePageKeys : KeysBase { /// /// (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. /// [KeyInfo(KeyType.Dictionary | KeyType.Required | KeyType.Inheritable, typeof(PdfResources))] public const string Resources = "/Resources"; /// /// (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. /// [KeyInfo(KeyType.Rectangle | KeyType.Required | KeyType.Inheritable)] public const string MediaBox = "/MediaBox"; /// /// (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. /// [KeyInfo(KeyType.Rectangle | KeyType.Optional | KeyType.Inheritable)] public const string CropBox = "/CropBox"; /// /// (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. /// [KeyInfo(KeyType.Integer | KeyType.Optional)] public const string Rotate = "/Rotate"; } /// /// Values inherited from a parent in the parent chain of a page tree. /// internal struct InheritedValues { public PdfDictionary Resources; public PdfRectangle MediaBox; public PdfRectangle CropBox; public PdfInteger Rotate; } } }