225 lines
9.4 KiB
C#
225 lines
9.4 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 PdfSharp.Pdf.IO;
|
|||
|
using PdfSharp.Pdf.Internal;
|
|||
|
|
|||
|
namespace PdfSharp.Pdf.Annotations
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Represents a link annotation.
|
|||
|
/// </summary>
|
|||
|
public sealed class PdfLinkAnnotation : PdfAnnotation
|
|||
|
{
|
|||
|
// Just a hack to make MigraDoc work with this code.
|
|||
|
enum LinkType
|
|||
|
{
|
|||
|
None, Document, Web, File
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes a new instance of the <see cref="PdfLinkAnnotation"/> class.
|
|||
|
/// </summary>
|
|||
|
public PdfLinkAnnotation()
|
|||
|
{
|
|||
|
_linkType = LinkType.None;
|
|||
|
Elements.SetName(PdfAnnotation.Keys.Subtype, "/Link");
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes a new instance of the <see cref="PdfLinkAnnotation"/> class.
|
|||
|
/// </summary>
|
|||
|
public PdfLinkAnnotation(PdfDocument document)
|
|||
|
: base(document)
|
|||
|
{
|
|||
|
_linkType = LinkType.None;
|
|||
|
Elements.SetName(PdfAnnotation.Keys.Subtype, "/Link");
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a link within the current document.
|
|||
|
/// </summary>
|
|||
|
/// <param name="rect">The link area in default page coordinates.</param>
|
|||
|
/// <param name="destinationPage">The one-based destination page number.</param>
|
|||
|
public static PdfLinkAnnotation CreateDocumentLink(PdfRectangle rect, int destinationPage)
|
|||
|
{
|
|||
|
if (destinationPage < 1)
|
|||
|
throw new ArgumentException("Invalid destination page in call to CreateDocumentLink: page number is one-based and must be 1 or higher.", "destinationPage");
|
|||
|
|
|||
|
PdfLinkAnnotation link = new PdfLinkAnnotation();
|
|||
|
link._linkType = LinkType.Document;
|
|||
|
link.Rectangle = rect;
|
|||
|
link._destPage = destinationPage;
|
|||
|
return link;
|
|||
|
}
|
|||
|
int _destPage;
|
|||
|
LinkType _linkType;
|
|||
|
string _url;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a link to the web.
|
|||
|
/// </summary>
|
|||
|
public static PdfLinkAnnotation CreateWebLink(PdfRectangle rect, string url)
|
|||
|
{
|
|||
|
PdfLinkAnnotation link = new PdfLinkAnnotation();
|
|||
|
link._linkType = PdfLinkAnnotation.LinkType.Web;
|
|||
|
link.Rectangle = rect;
|
|||
|
link._url = url;
|
|||
|
return link;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Creates a link to a file.
|
|||
|
/// </summary>
|
|||
|
public static PdfLinkAnnotation CreateFileLink(PdfRectangle rect, string fileName)
|
|||
|
{
|
|||
|
PdfLinkAnnotation link = new PdfLinkAnnotation();
|
|||
|
link._linkType = LinkType.File;
|
|||
|
// TODO: Adjust bleed box here (if possible)
|
|||
|
link.Rectangle = rect;
|
|||
|
link._url = fileName;
|
|||
|
return link;
|
|||
|
}
|
|||
|
|
|||
|
internal override void WriteObject(PdfWriter writer)
|
|||
|
{
|
|||
|
PdfPage dest = null;
|
|||
|
//pdf.AppendFormat(CultureInfo.InvariantCulture,
|
|||
|
// "{0} 0 obj\n<<\n/Type/Annot\n/Subtype/Link\n" +
|
|||
|
// "/Rect[{1} {2} {3} {4}]\n/BS<</Type/Border>>\n/Border[0 0 0]\n/C[0 0 0]\n",
|
|||
|
// ObjectID.ObjectNumber, rect.X1, rect.Y1, rect.X2, rect.Y2);
|
|||
|
|
|||
|
// Older Adobe Reader versions uses a border width of 0 as default value if neither Border nor BS are present.
|
|||
|
// But the PDF Reference specifies:
|
|||
|
// "If neither the Border nor the BS entry is present, the border is drawn as a solid line with a width of 1 point."
|
|||
|
// After this issue was fixed in newer Reader versions older PDFsharp created documents show an ugly solid border.
|
|||
|
// The following hack fixes this by specifying a 0 width border.
|
|||
|
if (Elements[PdfAnnotation.Keys.BS] == null)
|
|||
|
Elements[PdfAnnotation.Keys.BS] = new PdfLiteral("<</Type/Border/W 0>>");
|
|||
|
|
|||
|
// May be superfluous. See comment above.
|
|||
|
if (Elements[PdfAnnotation.Keys.Border] == null)
|
|||
|
Elements[PdfAnnotation.Keys.Border] = new PdfLiteral("[0 0 0]");
|
|||
|
|
|||
|
switch (_linkType)
|
|||
|
{
|
|||
|
case LinkType.None:
|
|||
|
break;
|
|||
|
|
|||
|
case LinkType.Document:
|
|||
|
// destIndex > Owner.PageCount can happen when rendering pages using PDFsharp directly.
|
|||
|
int destIndex = _destPage;
|
|||
|
if (destIndex > Owner.PageCount)
|
|||
|
destIndex = Owner.PageCount;
|
|||
|
destIndex--;
|
|||
|
dest = Owner.Pages[destIndex];
|
|||
|
//pdf.AppendFormat("/Dest[{0} 0 R/XYZ null null 0]\n", dest.ObjectID);
|
|||
|
Elements[Keys.Dest] = new PdfLiteral("[{0} 0 R/XYZ null null 0]", dest.ObjectNumber);
|
|||
|
break;
|
|||
|
|
|||
|
case LinkType.Web:
|
|||
|
//pdf.AppendFormat("/A<</S/URI/URI{0}>>\n", PdfEncoders.EncodeAsLiteral(url));
|
|||
|
Elements[PdfAnnotation.Keys.A] = new PdfLiteral("<</S/URI/URI{0}>>", //PdfEncoders.EncodeAsLiteral(url));
|
|||
|
PdfEncoders.ToStringLiteral(_url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler));
|
|||
|
break;
|
|||
|
|
|||
|
case LinkType.File:
|
|||
|
//pdf.AppendFormat("/A<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>\n",
|
|||
|
// PdfEncoders.EncodeAsLiteral(url));
|
|||
|
Elements[PdfAnnotation.Keys.A] = new PdfLiteral("<</Type/Action/S/Launch/F<</Type/Filespec/F{0}>> >>",
|
|||
|
//PdfEncoders.EncodeAsLiteral(url));
|
|||
|
PdfEncoders.ToStringLiteral(_url, PdfStringEncoding.WinAnsiEncoding, writer.SecurityHandler));
|
|||
|
break;
|
|||
|
}
|
|||
|
base.WriteObject(writer);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Predefined keys of this dictionary.
|
|||
|
/// </summary>
|
|||
|
internal new class Keys : PdfAnnotation.Keys
|
|||
|
{
|
|||
|
// /// <summary>
|
|||
|
// /// (Required) The type of annotation that this dictionary describes;
|
|||
|
// /// must be Link for a link annotation.
|
|||
|
// /// </summary>
|
|||
|
// inherited from base class
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; not permitted if an A entry is present) A destination to be displayed
|
|||
|
/// when the annotation is activated.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo(KeyType.ArrayOrNameOrString | KeyType.Optional)]
|
|||
|
public const string Dest = "/Dest";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.2) The annotation<6F>s highlighting mode, the visual effect to be
|
|||
|
/// used when the mouse button is pressed or held down inside its active area:
|
|||
|
/// N (None) No highlighting.
|
|||
|
/// I (Invert) Invert the contents of the annotation rectangle.
|
|||
|
/// O (Outline) Invert the annotation<6F>s border.
|
|||
|
/// P (Push) Display the annotation as if it were being pushed below the surface of the page.
|
|||
|
/// Default value: I.
|
|||
|
/// Note: In PDF 1.1, highlighting is always done by inverting colors inside the annotation rectangle.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.2", KeyType.Name | KeyType.Optional)]
|
|||
|
public const string H = "/H";
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// (Optional; PDF 1.3) A URI action formerly associated with this annotation. When Web
|
|||
|
/// Capture changes and annotation from a URI to a go-to action, it uses this entry to save
|
|||
|
/// the data from the original URI action so that it can be changed back in case the target page for
|
|||
|
/// the go-to action is subsequently deleted.
|
|||
|
/// </summary>
|
|||
|
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)]
|
|||
|
public const string PA = "/PA";
|
|||
|
|
|||
|
// QuadPoints
|
|||
|
|
|||
|
/// <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; }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|