This commit is contained in:
2021-05-25 17:00:45 +05:00
parent e2fcfed44c
commit ec2dac13d8
1172 changed files with 5636 additions and 5839 deletions

View File

@@ -0,0 +1,48 @@
#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 PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
internal interface IContentStream
{
PdfResources Resources { get; }
string GetFontName(XFont font, out PdfFont pdfFont);
string GetFontName(string idName, byte[] fontData, out PdfFont pdfFont);
string GetImageName(XImage image);
string GetFormName(XForm form);
}
}

View File

@@ -0,0 +1,230 @@

#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 PdfSharp.Drawing;
using PdfSharp.Pdf.Filters;
using PdfSharp.Fonts.OpenType;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a CIDFont dictionary.
/// </summary>
internal class PdfCIDFont : PdfFont
{
public PdfCIDFont(PdfDocument document)
: base(document)
{ }
public PdfCIDFont(PdfDocument document, PdfFontDescriptor fontDescriptor, XFont font)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/CIDFontType2");
PdfDictionary cid = new PdfDictionary();
cid.Elements.SetString("/Ordering", "Identity");
cid.Elements.SetString("/Registry", "Adobe");
cid.Elements.SetInteger("/Supplement", 0);
Elements.SetValue(Keys.CIDSystemInfo, cid);
FontDescriptor = fontDescriptor;
// ReSharper disable once DoNotCallOverridableMethodsInConstructor
Owner._irefTable.Add(fontDescriptor);
Elements[Keys.FontDescriptor] = fontDescriptor.Reference;
FontEncoding = font.PdfOptions.FontEncoding;
}
public PdfCIDFont(PdfDocument document, PdfFontDescriptor fontDescriptor, byte[] fontData)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/CIDFontType2");
PdfDictionary cid = new PdfDictionary();
cid.Elements.SetString("/Ordering", "Identity");
cid.Elements.SetString("/Registry", "Adobe");
cid.Elements.SetInteger("/Supplement", 0);
Elements.SetValue(Keys.CIDSystemInfo, cid);
FontDescriptor = fontDescriptor;
// ReSharper disable once DoNotCallOverridableMethodsInConstructor
Owner._irefTable.Add(fontDescriptor);
Elements[Keys.FontDescriptor] = fontDescriptor.Reference;
FontEncoding = PdfFontEncoding.Unicode;
}
public string BaseFont
{
get { return Elements.GetName(Keys.BaseFont); }
set { Elements.SetName(Keys.BaseFont, value); }
}
/// <summary>
/// Prepares the object to get saved.
/// </summary>
internal override void PrepareForSave()
{
base.PrepareForSave();
#if DEBUG_
if (FontDescriptor._descriptor.FontFace.loca == null)
{
GetType();
}
#endif
// CID fonts must be always embedded. PDFsharp embeds automatically a subset.
OpenTypeFontface subSet = null;
if (FontDescriptor._descriptor.FontFace.loca == null)
subSet = FontDescriptor._descriptor.FontFace;
else
subSet = FontDescriptor._descriptor.FontFace.CreateFontSubSet(_cmapInfo.GlyphIndices, true);
byte[] fontData = subSet.FontSource.Bytes;
PdfDictionary fontStream = new PdfDictionary(Owner);
Owner.Internals.AddObject(fontStream);
FontDescriptor.Elements[PdfFontDescriptor.Keys.FontFile2] = fontStream.Reference;
fontStream.Elements["/Length1"] = new PdfInteger(fontData.Length);
if (!Owner.Options.NoCompression)
{
fontData = Filtering.FlateDecode.Encode(fontData, _document.Options.FlateEncodeMode);
fontStream.Elements["/Filter"] = new PdfName("/FlateDecode");
}
fontStream.Elements["/Length"] = new PdfInteger(fontData.Length);
fontStream.CreateStream(fontData);
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public new sealed class Keys : PdfFont.Keys
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Font for a CIDFont dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Font")]
public new const string Type = "/Type";
/// <summary>
/// (Required) The type of CIDFont; CIDFontType0 or CIDFontType2.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string Subtype = "/Subtype";
/// <summary>
/// (Required) The PostScript name of the CIDFont. For Type 0 CIDFonts, this
/// is usually the value of the CIDFontName entry in the CIDFont program. For
/// Type 2 CIDFonts, it is derived the same way as for a simple TrueType font;
/// In either case, the name can have a subset prefix if appropriate.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string BaseFont = "/BaseFont";
/// <summary>
/// (Required) A dictionary containing entries that define the character collection
/// of the CIDFont.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required)]
public const string CIDSystemInfo = "/CIDSystemInfo";
/// <summary>
/// (Required; must be an indirect reference) A font descriptor describing the
/// CIDFonts default metrics other than its glyph widths.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.MustBeIndirect, typeof(PdfFontDescriptor))]
public new const string FontDescriptor = "/FontDescriptor";
/// <summary>
/// (Optional) The default width for glyphs in the CIDFont.
/// Default value: 1000.
/// </summary>
[KeyInfo(KeyType.Integer)]
public const string DW = "/DW";
/// <summary>
/// (Optional) A description of the widths for the glyphs in the CIDFont. The
/// arrays elements have a variable format that can specify individual widths
/// for consecutive CIDs or one width for a range of CIDs.
/// Default value: none (the DW value is used for all glyphs).
/// </summary>
[KeyInfo(KeyType.Array, typeof(PdfArray))]
public const string W = "/W";
/// <summary>
/// (Optional; applies only to CIDFonts used for vertical writing) An array of two
/// numbers specifying the default metrics for vertical writing.
/// Default value: [880 1000].
/// </summary>
[KeyInfo(KeyType.Array)]
public const string DW2 = "/DW2";
/// <summary>
/// (Optional; applies only to CIDFonts used for vertical writing) A description
/// of the metrics for vertical writing for the glyphs in the CIDFont.
/// Default value: none (the DW2 value is used for all glyphs).
/// </summary>
[KeyInfo(KeyType.Array, typeof(PdfArray))]
public const string W2 = "/W2";
/// <summary>
/// (Optional; Type 2 CIDFonts only) A specification of the mapping from CIDs
/// to glyph indices. If the value is a stream, the bytes in the stream contain the
/// mapping from CIDs to glyph indices: the glyph index for a particular CID
/// value c is a 2-byte value stored in bytes 2 × c and 2 × c + 1, where the first
/// byte is the high-order byte. If the value of CIDToGIDMap is a name, it must
/// be Identity, indicating that the mapping between CIDs and glyph indices is
/// the identity mapping.
/// Default value: Identity.
/// This entry may appear only in a Type 2 CIDFont whose associated True-Type font
/// program is embedded in the PDF file.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.StreamOrName)]
public const string CIDToGIDMap = "/CIDToGIDMap";
/// <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; }
}
}
}

View File

@@ -0,0 +1,463 @@
#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.AcroForms;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents the catalog dictionary.
/// </summary>
public sealed class PdfCatalog : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfCatalog"/> class.
/// </summary>
public PdfCatalog(PdfDocument document)
: base(document)
{
Elements.SetName(Keys.Type, "/Catalog");
_version = "1.4"; // HACK in PdfCatalog
}
internal PdfCatalog(PdfDictionary dictionary)
: base(dictionary)
{ }
/// <summary>
/// Get or sets the version of the PDF specification to which the document conforms.
/// </summary>
public string Version
{
get { return _version; }
set
{
switch (value)
{
case "1.0":
case "1.1":
case "1.2":
throw new InvalidOperationException("Unsupported PDF version.");
case "1.3":
case "1.4":
_version = value;
break;
case "1.5":
case "1.6":
throw new InvalidOperationException("Unsupported PDF version.");
default:
throw new ArgumentException("Invalid version.");
}
}
}
string _version = "1.3";
/// <summary>
/// Gets the pages collection of this document.
/// </summary>
public PdfPages Pages
{
get
{
if (_pages == null)
{
_pages = (PdfPages)Elements.GetValue(Keys.Pages, VCF.CreateIndirect);
if (Owner.IsImported)
_pages.FlattenPageTree();
}
return _pages;
}
}
PdfPages _pages;
/// <summary>
/// Implementation of PdfDocument.PageLayout.
/// </summary>
internal PdfPageLayout PageLayout
{
get { return (PdfPageLayout)Elements.GetEnumFromName(Keys.PageLayout, PdfPageLayout.SinglePage); }
set { Elements.SetEnumAsName(Keys.PageLayout, value); }
}
/// <summary>
/// Implementation of PdfDocument.PageMode.
/// </summary>
internal PdfPageMode PageMode
{
get { return (PdfPageMode)Elements.GetEnumFromName(Keys.PageMode, PdfPageMode.UseNone); }
set { Elements.SetEnumAsName(Keys.PageMode, value); }
}
/// <summary>
/// Implementation of PdfDocument.ViewerPreferences.
/// </summary>
internal PdfViewerPreferences ViewerPreferences
{
get
{
if (_viewerPreferences == null)
_viewerPreferences = (PdfViewerPreferences)Elements.GetValue(Keys.ViewerPreferences, VCF.CreateIndirect);
return _viewerPreferences;
}
}
PdfViewerPreferences _viewerPreferences;
/// <summary>
/// Implementation of PdfDocument.Outlines.
/// </summary>
internal PdfOutlineCollection Outlines
{
get
{
if (_outline == null)
{
////// Ensure that the page tree exists.
////// ReSharper disable once UnusedVariable because we need dummy to call the getter.
////PdfPages dummy = Pages;
// Now create the outline item tree.
_outline = (PdfOutline)Elements.GetValue(Keys.Outlines, VCF.CreateIndirect);
}
return _outline.Outlines;
}
}
PdfOutline _outline;
/// <summary>
/// Gets the AcroForm dictionary of this document.
/// </summary>
public PdfAcroForm AcroForm
{
get
{
if (_acroForm == null)
_acroForm = (PdfAcroForm)Elements.GetValue(Keys.AcroForm);
return _acroForm;
}
}
PdfAcroForm _acroForm;
/// <summary>
/// Gets or sets the language identifier specifying the natural language for all text in the document.
/// Sample values are 'en-US' for 'English United States' or 'de-DE' for 'deutsch Deutschland' (i.e. 'German Germany').
/// </summary>
public string Language
{
get { return Elements.GetString(Keys.Lang); }
set
{
if (value == null)
Elements.Remove(Keys.Lang);
else
Elements.SetString(Keys.Lang, value);
}
}
/// <summary>
/// Dispatches PrepareForSave to the objects that need it.
/// </summary>
internal override void PrepareForSave()
{
// Prepare pages.
if (_pages != null)
_pages.PrepareForSave();
// Create outline objects.
if (_outline != null && _outline.Outlines.Count > 0)
{
if (Elements[Keys.PageMode] == null)
PageMode = PdfPageMode.UseOutlines;
_outline.PrepareForSave();
}
}
internal override void WriteObject(PdfWriter writer)
{
if (_outline != null && _outline.Outlines.Count > 0)
{
if (Elements[Keys.PageMode] == null)
PageMode = PdfPageMode.UseOutlines;
}
base.WriteObject(writer);
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
internal sealed class Keys : KeysBase
{
// ReSharper disable InconsistentNaming
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Catalog for the catalog dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Catalog")]
public const string Type = "/Type";
/// <summary>
/// (Optional; PDF 1.4) The version of the PDF specification to which the document
/// conforms (for example, 1.4) if later than the version specified in the file<6C>s header.
/// If the header specifies a later version, or if this entry is absent, the document
/// conforms to the version specified in the header. This entry enables a PDF producer
/// application to update the version using an incremental update.
/// </summary>
[KeyInfo("1.4", KeyType.Name | KeyType.Optional)]
public const string Version = "/Version";
/// <summary>
/// (Required; must be an indirect reference) The page tree node that is the root of
/// the document<6E>s page tree.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required | KeyType.MustBeIndirect, typeof(PdfPages))]
public const string Pages = "/Pages";
/// <summary>
/// (Optional; PDF 1.3) A number tree defining the page labeling for the document.
/// The keys in this tree are page indices; the corresponding values are page label dictionaries.
/// Each page index denotes the first page in a labeling range to which the specified page
/// label dictionary applies. The tree must include a value for pageindex 0.
/// </summary>
[KeyInfo("1.3", KeyType.NumberTree | KeyType.Optional)]
public const string PageLabels = "/PageLabels";
/// <summary>
/// (Optional; PDF 1.2) The document<6E>s name dictionary.
/// </summary>
[KeyInfo("1.2", KeyType.Dictionary | KeyType.Optional)]
public const string Names = "/Names";
/// <summary>
/// (Optional; PDF 1.1; must be an indirect reference) A dictionary of names and
/// corresponding destinations.
/// </summary>
[KeyInfo("1.1", KeyType.Dictionary | KeyType.Optional)]
public const string Dests = "/Dests";
/// <summary>
/// (Optional; PDF 1.2) A viewer preferences dictionary specifying the way the document
/// is to be displayed on the screen. If this entry is absent, applications should use
/// their own current user preference settings.
/// </summary>
[KeyInfo("1.2", KeyType.Dictionary | KeyType.Optional, typeof(PdfViewerPreferences))]
public const string ViewerPreferences = "/ViewerPreferences";
/// <summary>
/// (Optional) A name object specifying the page layout to be used when the document is
/// opened:
/// SinglePage - Display one page at a time.
/// OneColumn - Display the pages in one column.
/// TwoColumnLeft - Display the pages in two columns, with oddnumbered pages on the left.
/// TwoColumnRight - Display the pages in two columns, with oddnumbered pages on the right.
/// TwoPageLeft - (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
/// TwoPageRight - (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string PageLayout = "/PageLayout";
/// <summary>
/// (Optional) A name object specifying how the document should be displayed when opened:
/// UseNone - Neither document outline nor thumbnail images visible.
/// UseOutlines - Document outline visible.
/// UseThumbs - Thumbnail images visible.
/// FullScreen - Full-screen mode, with no menu bar, windowcontrols, or any other window visible.
/// UseOC - (PDF 1.5) Optional content group panel visible.
/// UseAttachments (PDF 1.6) Attachments panel visible.
/// Default value: UseNone.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string PageMode = "/PageMode";
/// <summary>
/// (Optional; must be an indirect reference) The outline dictionary that is the root
/// of the document<6E>s outline hierarchy.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfOutline))]
public const string Outlines = "/Outlines";
/// <summary>
/// (Optional; PDF 1.1; must be an indirect reference) An array of thread dictionaries
/// representing the document<6E>s article threads.
/// </summary>
[KeyInfo("1.1", KeyType.Array | KeyType.Optional)]
public const string Threads = "/Threads";
/// <summary>
/// (Optional; PDF 1.1) A value specifying a destination to be displayed or an action to be
/// performed when the document is opened. The value is either an array defining a destination
/// or an action dictionary representing an action. If this entry is absent, the document
/// should be opened to the top of the first page at the default magnification factor.
/// </summary>
[KeyInfo("1.1", KeyType.ArrayOrDictionary | KeyType.Optional)]
public const string OpenAction = "/OpenAction";
/// <summary>
/// (Optional; PDF 1.4) An additional-actions dictionary defining the actions to be taken
/// in response to various trigger events affecting the document as a whole.
/// </summary>
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)]
public const string AA = "/AA";
/// <summary>
/// (Optional; PDF 1.1) A URI dictionary containing document-level information for URI
/// (uniform resource identifier) actions.
/// </summary>
[KeyInfo("1.1", KeyType.Dictionary | KeyType.Optional)]
public const string URI = "/URI";
/// <summary>
/// (Optional; PDF 1.2) The document<6E>s interactive form (AcroForm) dictionary.
/// </summary>
[KeyInfo("1.2", KeyType.Dictionary | KeyType.Optional, typeof(PdfAcroForm))]
public const string AcroForm = "/AcroForm";
/// <summary>
/// (Optional; PDF 1.4; must be an indirect reference) A metadata stream
/// containing metadata for the document.
/// </summary>
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional | KeyType.MustBeIndirect)]
public const string Metadata = "/Metadata";
/// <summary>
/// (Optional; PDF 1.3) The document<6E>s structure tree root dictionary.
/// </summary>
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)]
public const string StructTreeRoot = "/StructTreeRoot";
/// <summary>
/// (Optional; PDF 1.4) A mark information dictionary containing information
/// about the document<6E>s usage of Tagged PDF conventions.
/// </summary>
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)]
public const string MarkInfo = "/MarkInfo";
/// <summary>
/// (Optional; PDF 1.4) A language identifier specifying the natural language for all
/// text in the document except where overridden by language specifications for structure
/// elements or marked content. If this entry is absent, the language is considered unknown.
/// </summary>
[KeyInfo("1.4", KeyType.String | KeyType.Optional)]
public const string Lang = "/Lang";
/// <summary>
/// (Optional; PDF 1.3) A Web Capture information dictionary containing state information
/// used by the Acrobat Web Capture (AcroSpider) plugin extension.
/// </summary>
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional)]
public const string SpiderInfo = "/SpiderInfo";
/// <summary>
/// (Optional; PDF 1.4) An array of output intent dictionaries describing the color
/// characteristics of output devices on which the document might be rendered.
/// </summary>
[KeyInfo("1.4", KeyType.Array | KeyType.Optional)]
public const string OutputIntents = "/OutputIntents";
/// <summary>
/// (Optional; PDF 1.4) A page-piece dictionary associated with the document.
/// </summary>
[KeyInfo("1.4", KeyType.Dictionary | KeyType.Optional)]
public const string PieceInfo = "/PieceInfo";
/// <summary>
/// (Optional; PDF 1.5; required if a document contains optional content) The document<6E>s
/// optional content properties dictionary.
/// </summary>
[KeyInfo("1.5", KeyType.Dictionary | KeyType.Optional)]
public const string OCProperties = "/OCProperties";
/// <summary>
/// (Optional; PDF 1.5) A permissions dictionary that specifies user access permissions
/// for the document.
/// </summary>
[KeyInfo("1.5", KeyType.Dictionary | KeyType.Optional)]
public const string Perms = "/Perms";
/// <summary>
/// (Optional; PDF 1.5) A dictionary containing attestations regarding the content of a
/// PDF document, as it relates to the legality of digital signatures.
/// </summary>
[KeyInfo("1.5", KeyType.Dictionary | KeyType.Optional)]
public const string Legal = "/Legal";
/// <summary>
/// (Optional; PDF 1.7) An array of requirement dictionaries representing
/// requirements for the document.
/// </summary>
[KeyInfo("1.7", KeyType.Array | KeyType.Optional)]
public const string Requirements = "/Requirements";
/// <summary>
/// (Optional; PDF 1.7) A collection dictionary that a PDF consumer uses to enhance
/// the presentation of file attachments stored in the PDF document.
/// </summary>
[KeyInfo("1.7", KeyType.Dictionary | KeyType.Optional)]
public const string Collection = "/Collection";
/// <summary>
/// (Optional; PDF 1.7) A flag used to expedite the display of PDF documents containing XFA forms.
/// It specifies whether the document must be regenerated when the document is first opened.
/// If true, the viewer application treats the document as a shell and regenerates the content
/// when the document is opened, regardless of any dynamic forms settings that appear in the XFA
/// stream itself. This setting is used to expedite the display of documents whose layout varies
/// depending on the content of the XFA streams.
/// If false, the viewer application does not regenerate the content when the document is opened.
/// See the XML Forms Architecture (XFA) Specification (Bibliography).
/// Default value: false.
/// </summary>
[KeyInfo("1.7", KeyType.Boolean | KeyType.Optional)]
public const string NeedsRendering = "/NeedsRendering";
// ReSharper restore InconsistentNaming
/// <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; }
}
}
}

View File

@@ -0,0 +1,192 @@
#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; }
}
}
}

View File

@@ -0,0 +1,267 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.Collections;
using PdfSharp.Pdf.Content.Objects;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents an array of PDF content streams of a page.
/// </summary>
public sealed class PdfContents : PdfArray
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfContents"/> class.
/// </summary>
/// <param name="document">The document.</param>
public PdfContents(PdfDocument document)
: base(document)
{ }
internal PdfContents(PdfArray array)
: base(array)
{
int count = Elements.Count;
for (int idx = 0; idx < count; idx++)
{
// Convert the references from PdfDictionary to PdfContent
PdfItem item = Elements[idx];
PdfReference iref = item as PdfReference;
if (iref != null && iref.Value is PdfDictionary)
{
// The following line is correct!
new PdfContent((PdfDictionary)iref.Value);
}
else
throw new InvalidOperationException("Unexpected item in a content stream array.");
}
}
/// <summary>
/// Appends a new content stream and returns it.
/// </summary>
public PdfContent AppendContent()
{
Debug.Assert(Owner != null);
SetModified();
PdfContent content = new PdfContent(Owner);
Owner._irefTable.Add(content);
Debug.Assert(content.Reference != null);
Elements.Add(content.Reference);
return content;
}
/// <summary>
/// Prepends a new content stream and returns it.
/// </summary>
public PdfContent PrependContent()
{
Debug.Assert(Owner != null);
SetModified();
PdfContent content = new PdfContent(Owner);
Owner._irefTable.Add(content);
Debug.Assert(content.Reference != null);
Elements.Insert(0, content.Reference);
return content;
}
/// <summary>
/// Creates a single content stream with the bytes from the array of the content streams.
/// This operation does not modify any of the content streams in this array.
/// </summary>
public PdfContent CreateSingleContent()
{
byte[] bytes = new byte[0];
byte[] bytes1;
byte[] bytes2;
foreach (PdfItem iref in Elements)
{
PdfDictionary cont = (PdfDictionary)((PdfReference)iref).Value;
bytes1 = bytes;
bytes2 = cont.Stream.UnfilteredValue;
bytes = new byte[bytes1.Length + bytes2.Length + 1];
bytes1.CopyTo(bytes, 0);
bytes[bytes1.Length] = (byte)'\n';
bytes2.CopyTo(bytes, bytes1.Length + 1);
}
PdfContent content = new PdfContent(Owner);
content.Stream = new PdfDictionary.PdfStream(bytes, content);
return content;
}
/// <summary>
/// Replaces the current content of the page with the specified content sequence.
/// </summary>
public PdfContent ReplaceContent(CSequence cseq)
{
if (cseq == null)
throw new ArgumentNullException(nameof(cseq));
return ReplaceContent(cseq.ToContent());
}
/// <summary>
/// Replaces the current content of the page with the specified bytes.
/// </summary>
PdfContent ReplaceContent(byte[] contentBytes)
{
Debug.Assert(Owner != null);
PdfContent content = new PdfContent(Owner);
content.CreateStream(contentBytes);
Owner._irefTable.Add(content);
Elements.Clear();
Elements.Add(content.Reference);
return content;
}
void SetModified()
{
if (!_modified)
{
_modified = true;
int count = Elements.Count;
if (count == 1)
{
PdfContent content = (PdfContent)((PdfReference)Elements[0]).Value;
content.PreserveGraphicsState();
}
else if (count > 1)
{
// Surround content streams with q/Q operations
byte[] value;
int length;
PdfContent content = (PdfContent)((PdfReference)Elements[0]).Value;
if (content != null && content.Stream != null)
{
length = content.Stream.Length;
value = new byte[length + 2];
value[0] = (byte)'q';
value[1] = (byte)'\n';
Array.Copy(content.Stream.Value, 0, value, 2, length);
content.Stream.Value = value;
content.Elements.SetInteger("/Length", length + 2);
}
content = (PdfContent)((PdfReference)Elements[count - 1]).Value;
if (content != null && content.Stream != null)
{
length = content.Stream.Length;
value = new byte[length + 3];
Array.Copy(content.Stream.Value, 0, value, 0, length);
value[length] = (byte)' ';
value[length + 1] = (byte)'Q';
value[length + 2] = (byte)'\n';
content.Stream.Value = value;
content.Elements.SetInteger("/Length", length + 3);
}
}
}
}
bool _modified;
internal override void WriteObject(PdfWriter writer)
{
// Save two bytes in PDF stream...
if (Elements.Count == 1)
Elements[0].WriteObject(writer);
else
base.WriteObject(writer);
}
/// <summary>
/// Gets the enumerator.
/// </summary>
public new IEnumerator<PdfContent> GetEnumerator()
{
return new PdfPageContentEnumerator(this);
}
class PdfPageContentEnumerator : IEnumerator<PdfContent>
{
internal PdfPageContentEnumerator(PdfContents list)
{
_contents = list;
_index = -1;
}
public bool MoveNext()
{
if (_index < _contents.Elements.Count - 1)
{
_index++;
_currentElement = (PdfContent)((PdfReference)_contents.Elements[_index]).Value;
return true;
}
_index = _contents.Elements.Count;
return false;
}
public void Reset()
{
_currentElement = null;
_index = -1;
}
object IEnumerator.Current
{
get { return Current; }
}
public PdfContent Current
{
get
{
if (_index == -1 || _index >= _contents.Elements.Count)
throw new InvalidOperationException(PSSR.ListEnumCurrentOutOfRange);
return _currentElement;
}
}
public void Dispose()
{
// Nothing to do.
}
PdfContent _currentElement;
int _index;
readonly PdfContents _contents;
}
}
}

View File

@@ -0,0 +1,157 @@
#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.Collections.Generic;
using System.Diagnostics;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF cross-reference stream.
/// </summary>
internal sealed class PdfCrossReferenceStream : PdfTrailer // Reference: 3.4.7 Cross-Reference Streams / Page 106
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfObjectStream"/> class.
/// </summary>
public PdfCrossReferenceStream(PdfDocument document)
: base(document)
{
#if DEBUG && CORE
if (Internal.PdfDiagnostics.TraceXrefStreams)
{
Debug.WriteLine("PdfCrossReferenceStream created.");
}
#endif
}
public readonly List<CrossReferenceStreamEntry> Entries = new List<CrossReferenceStreamEntry>();
public struct CrossReferenceStreamEntry
{
// Reference: TABLE 3.16 Entries in a cross-reference stream / Page 109
public uint Type; // 0, 1, or 2.
public uint Field2;
public uint Field3;
}
/// <summary>
/// Predefined keys for cross-reference dictionaries.
/// </summary>
public new class Keys : PdfTrailer.Keys // Reference: TABLE 3.15 Additional entries specific to a cross-reference stream dictionary / Page 107
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be XRef for a cross-reference stream.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "XRef")]
public const string Type = "/Type";
/// <summary>
/// (Required) The number one greater than the highest object number
/// used in this section or in any section for which this is an update.
/// It is equivalent to the Size entry in a trailer dictionary.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public new const string Size = "/Size";
/// <summary>
/// (Optional) An array containing a pair of integers for each subsection in this section.
/// The first integer is the first object number in the subsection; the second integer
/// is the number of entries in the subsection.
/// The array is sorted in ascending order by object number. Subsections cannot overlap;
/// an object number may have at most one entry in a section.
/// Default value: [0 Size].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Index = "/Index";
/// <summary>
/// (Present only if the file has more than one cross-reference stream; not meaningful in
/// hybrid-reference files) The byte offset from the beginning of the file to the beginning
/// of the previous cross-reference stream. This entry has the same function as the Prev
/// entry in the trailer dictionary.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public new const string Prev = "/Prev";
/// <summary>
/// (Required) An array of integers representing the size of the fields in a single
/// cross-reference entry. The table describes the types of entries and their fields.
/// For PDF 1.5, W always contains three integers; the value of each integer is the
/// number of bytes (in the decoded stream) of the corresponding field. For example,
/// [1 2 1] means that the fields are one byte, two bytes, and one byte, respectively.
///
/// A value of zero for an element in the W array indicates that the corresponding field
/// is not present in the stream, and the default value is used, if there is one. If the
/// first element is zero, the type field is not present, and it defaults to type 1.
///
/// The sum of the items is the total length of each entry; it can be used with the
/// Indexarray to determine the starting position of each subsection.
///
/// Note: Different cross-reference streams in a PDF file may use different values for W.
///
/// Entries in a cross-reference stream.
///
/// TYPE FIELD DESCRIPTION
/// 0 1 The type of this entry, which must be 0. Type 0 entries define the linked list of free objects (corresponding to f entries in a cross-reference table).
/// 2 The object number of the next free object.
/// 3 The generation number to use if this object number is used again.
/// 1 1 The type of this entry, which must be 1. Type 1 entries define objects that are in use but are not compressed (corresponding to n entries in a cross-reference table).
/// 2 The byte offset of the object, starting from the beginning of the file.
/// 3 The generation number of the object. Default value: 0.
/// 2 1 The type of this entry, which must be 2. Type 2 entries define compressed objects.
/// 2 The object number of the object stream in which this object is stored. (The generation number of the object stream is implicitly 0.)
/// 3 The index of this object within the object stream.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Required)]
public const string W = "/W";
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
public static new 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; }
}
}
}

View File

@@ -0,0 +1,590 @@
#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.Collections;
using System.Collections.Generic;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents the cross-reference table of a PDF document.
/// It contains all indirect objects of a document.
/// </summary>
internal sealed class PdfCrossReferenceTable // Must not be derive from PdfObject.
{
public PdfCrossReferenceTable(PdfDocument document)
{
_document = document;
}
readonly PdfDocument _document;
/// <summary>
/// Represents the relation between PdfObjectID and PdfReference for a PdfDocument.
/// </summary>
public Dictionary<PdfObjectID, PdfReference> ObjectTable = new Dictionary<PdfObjectID, PdfReference>();
internal bool IsUnderConstruction
{
get { return _isUnderConstruction; }
set { _isUnderConstruction = value; }
}
bool _isUnderConstruction;
/// <summary>
/// Adds a cross reference entry to the table. Used when parsing the trailer.
/// </summary>
public void Add(PdfReference iref)
{
#if DEBUG
if (iref.ObjectID.ObjectNumber == 948)
GetType();
#endif
if (iref.ObjectID.IsEmpty)
iref.ObjectID = new PdfObjectID(GetNewObjectNumber());
if (ObjectTable.ContainsKey(iref.ObjectID))
throw new InvalidOperationException("Object already in table.");
ObjectTable.Add(iref.ObjectID, iref);
}
/// <summary>
/// Adds a PdfObject to the table.
/// </summary>
public void Add(PdfObject value)
{
if (value.Owner == null)
value.Document = _document;
else
Debug.Assert(value.Owner == _document);
if (value.ObjectID.IsEmpty)
value.SetObjectID(GetNewObjectNumber(), 0);
if (ObjectTable.ContainsKey(value.ObjectID))
throw new InvalidOperationException("Object already in table.");
ObjectTable.Add(value.ObjectID, value.Reference);
}
public void Remove(PdfReference iref)
{
ObjectTable.Remove(iref.ObjectID);
}
/// <summary>
/// Gets a cross reference entry from an object identifier.
/// Returns null if no object with the specified ID exists in the object table.
/// </summary>
public PdfReference this[PdfObjectID objectID]
{
get
{
PdfReference iref;
ObjectTable.TryGetValue(objectID, out iref);
return iref;
}
}
/// <summary>
/// Indicates whether the specified object identifier is in the table.
/// </summary>
public bool Contains(PdfObjectID objectID)
{
return ObjectTable.ContainsKey(objectID);
}
//public PdfObject GetObject(PdfObjectID objectID)
//{
// return this[objectID].Value;
//}
// /// <summary>
// /// Gets the entry for the specified object, or null, if the object is not in
// /// this XRef table.
// /// </summary>
// internal PdfReference GetEntry(PdfObjectID objectID)
// {
// return this[objectID];
// }
/// <summary>
/// Returns the next free object number.
/// </summary>
public int GetNewObjectNumber()
{
// New objects are numbered consecutively. If a document is imported, maxObjectNumber is
// set to the highest object number used in the document.
return ++_maxObjectNumber;
}
internal int _maxObjectNumber;
/// <summary>
/// Writes the xref section in pdf stream.
/// </summary>
internal void WriteObject(PdfWriter writer)
{
writer.WriteRaw("xref\n");
PdfReference[] irefs = AllReferences;
int count = irefs.Length;
writer.WriteRaw(String.Format("0 {0}\n", count + 1));
writer.WriteRaw(String.Format("{0:0000000000} {1:00000} {2} \n", 0, 65535, "f"));
//PdfEncoders.WriteAnsi(stream, text);
for (int idx = 0; idx < count; idx++)
{
PdfReference iref = irefs[idx];
// Acrobat is very pedantic; it must be exactly 20 bytes per line.
writer.WriteRaw(String.Format("{0:0000000000} {1:00000} {2} \n", iref.Position, iref.GenerationNumber, "n"));
}
}
/// <summary>
/// Gets an array of all object identifiers. For debugging purposes only.
/// </summary>
internal PdfObjectID[] AllObjectIDs
{
get
{
ICollection collection = ObjectTable.Keys;
PdfObjectID[] objectIDs = new PdfObjectID[collection.Count];
collection.CopyTo(objectIDs, 0);
return objectIDs;
}
}
/// <summary>
/// Gets an array of all cross references in ascending order by their object identifier.
/// </summary>
internal PdfReference[] AllReferences
{
get
{
Dictionary<PdfObjectID, PdfReference>.ValueCollection collection = ObjectTable.Values;
List<PdfReference> list = new List<PdfReference>(collection);
list.Sort(PdfReference.Comparer);
PdfReference[] irefs = new PdfReference[collection.Count];
list.CopyTo(irefs, 0);
return irefs;
}
}
internal void HandleOrphanedReferences()
{ }
/// <summary>
/// Removes all objects that cannot be reached from the trailer.
/// Returns the number of removed objects.
/// </summary>
internal int Compact()
{
// TODO: remove PdfBooleanObject, PdfIntegerObject etc.
int removed = ObjectTable.Count;
//CheckConsistence();
// TODO: Is this really so easy?
PdfReference[] irefs = TransitiveClosure(_document._trailer);
#if DEBUG
// Have any two objects the same ID?
Dictionary<int, int> ids = new Dictionary<int, int>();
foreach (PdfObjectID objID in ObjectTable.Keys)
{
ids.Add(objID.ObjectNumber, 0);
}
// Have any two irefs the same value?
//Dictionary<int, int> ids = new Dictionary<int, int>();
ids.Clear();
foreach (PdfReference iref in ObjectTable.Values)
{
ids.Add(iref.ObjectNumber, 0);
}
//
Dictionary<PdfReference, int> refs = new Dictionary<PdfReference, int>();
foreach (PdfReference iref in irefs)
{
refs.Add(iref, 0);
}
foreach (PdfReference value in ObjectTable.Values)
{
if (!refs.ContainsKey(value))
value.GetType();
}
foreach (PdfReference iref in ObjectTable.Values)
{
if (iref.Value == null)
GetType();
Debug.Assert(iref.Value != null);
}
foreach (PdfReference iref in irefs)
{
if (!ObjectTable.ContainsKey(iref.ObjectID))
GetType();
Debug.Assert(ObjectTable.ContainsKey(iref.ObjectID));
if (iref.Value == null)
GetType();
Debug.Assert(iref.Value != null);
}
#endif
_maxObjectNumber = 0;
ObjectTable.Clear();
foreach (PdfReference iref in irefs)
{
// This if is needed for corrupt PDF files from the wild.
// Without the if, an exception will be thrown if the file contains duplicate IDs ("An item with the same key has already been added to the dictionary.").
// With the if, the first object with the ID will be used and later objects with the same ID will be ignored.
if (!ObjectTable.ContainsKey(iref.ObjectID))
{
ObjectTable.Add(iref.ObjectID, iref);
_maxObjectNumber = Math.Max(_maxObjectNumber, iref.ObjectNumber);
}
}
//CheckConsistence();
removed -= ObjectTable.Count;
return removed;
}
/// <summary>
/// Renumbers the objects starting at 1.
/// </summary>
internal void Renumber()
{
//CheckConsistence();
PdfReference[] irefs = AllReferences;
ObjectTable.Clear();
// Give all objects a new number.
int count = irefs.Length;
for (int idx = 0; idx < count; idx++)
{
PdfReference iref = irefs[idx];
#if DEBUG_
if (iref.ObjectNumber == 1108)
GetType();
#endif
iref.ObjectID = new PdfObjectID(idx + 1);
// Rehash with new number.
ObjectTable.Add(iref.ObjectID, iref);
}
_maxObjectNumber = count;
//CheckConsistence();
}
/// <summary>
/// Checks the logical consistence for debugging purposes (useful after reconstruction work).
/// </summary>
[Conditional("DEBUG_")]
public void CheckConsistence()
{
Dictionary<PdfReference, object> ht1 = new Dictionary<PdfReference, object>();
foreach (PdfReference iref in ObjectTable.Values)
{
Debug.Assert(!ht1.ContainsKey(iref), "Duplicate iref.");
Debug.Assert(iref.Value != null);
ht1.Add(iref, null);
}
Dictionary<PdfObjectID, object> ht2 = new Dictionary<PdfObjectID, object>();
foreach (PdfReference iref in ObjectTable.Values)
{
Debug.Assert(!ht2.ContainsKey(iref.ObjectID), "Duplicate iref.");
ht2.Add(iref.ObjectID, null);
}
ICollection collection = ObjectTable.Values;
int count = collection.Count;
PdfReference[] irefs = new PdfReference[count];
collection.CopyTo(irefs, 0);
#if true
for (int i = 0; i < count; i++)
for (int j = 0; j < count; j++)
if (i != j)
{
Debug.Assert(ReferenceEquals(irefs[i].Document, _document));
Debug.Assert(irefs[i] != irefs[j]);
Debug.Assert(!ReferenceEquals(irefs[i], irefs[j]));
Debug.Assert(!ReferenceEquals(irefs[i].Value, irefs[j].Value));
Debug.Assert(!Equals(irefs[i].ObjectID, irefs[j].Value.ObjectID));
Debug.Assert(irefs[i].ObjectNumber != irefs[j].Value.ObjectNumber);
Debug.Assert(ReferenceEquals(irefs[i].Document, irefs[j].Document));
GetType();
}
#endif
}
///// <summary>
///// The garbage collector for PDF objects.
///// </summary>
//public sealed class GC
//{
// PdfXRefTable xrefTable;
//
// internal GC(PdfXRefTable xrefTable)
// {
// _xrefTable = xrefTable;
// }
//
// public void Collect()
// { }
//
// public PdfReference[] ReachableObjects()
// {
// Hash_table objects = new Hash_table();
// TransitiveClosure(objects, _xrefTable.document.trailer);
// }
/// <summary>
/// Calculates the transitive closure of the specified PdfObject, i.e. all indirect objects
/// recursively reachable from the specified object.
/// </summary>
public PdfReference[] TransitiveClosure(PdfObject pdfObject)
{
return TransitiveClosure(pdfObject, short.MaxValue);
}
/// <summary>
/// Calculates the transitive closure of the specified PdfObject with the specified depth, i.e. all indirect objects
/// recursively reachable from the specified object in up to maximally depth steps.
/// </summary>
public PdfReference[] TransitiveClosure(PdfObject pdfObject, int depth)
{
CheckConsistence();
Dictionary<PdfItem, object> objects = new Dictionary<PdfItem, object>();
_overflow = new Dictionary<PdfItem, object>();
TransitiveClosureImplementation(objects, pdfObject);
TryAgain:
if (_overflow.Count > 0)
{
PdfObject[] array = new PdfObject[_overflow.Count];
_overflow.Keys.CopyTo(array, 0);
_overflow = new Dictionary<PdfItem, object>();
for (int idx = 0; idx < array.Length; idx++)
{
PdfObject obj = array[idx];
TransitiveClosureImplementation(objects, obj);
}
goto TryAgain;
}
CheckConsistence();
ICollection collection = objects.Keys;
int count = collection.Count;
PdfReference[] irefs = new PdfReference[count];
collection.CopyTo(irefs, 0);
#if true_
for (int i = 0; i < count; i++)
for (int j = 0; j < count; j++)
if (i != j)
{
Debug.Assert(ReferenceEquals(irefs[i].Document, _document));
Debug.Assert(irefs[i] != irefs[j]);
Debug.Assert(!ReferenceEquals(irefs[i], irefs[j]));
Debug.Assert(!ReferenceEquals(irefs[i].Value, irefs[j].Value));
Debug.Assert(!Equals(irefs[i].ObjectID, irefs[j].Value.ObjectID));
Debug.Assert(irefs[i].ObjectNumber != irefs[j].Value.ObjectNumber);
Debug.Assert(ReferenceEquals(irefs[i].Document, irefs[j].Document));
GetType();
}
#endif
return irefs;
}
static int _nestingLevel;
Dictionary<PdfItem, object> _overflow = new Dictionary<PdfItem, object>();
void TransitiveClosureImplementation(Dictionary<PdfItem, object> objects, PdfObject pdfObject/*, ref int depth*/)
{
try
{
_nestingLevel++;
if (_nestingLevel >= 1000)
{
if (!_overflow.ContainsKey(pdfObject))
_overflow.Add(pdfObject, null);
return;
}
#if DEBUG_
//enterCount++;
if (enterCount == 5400)
GetType();
//if (!Object.ReferenceEquals(pdfObject.Owner, _document))
// GetType();
//////Debug.Assert(Object.ReferenceEquals(pdfObject27.Document, _document));
// if (item is PdfObject && ((PdfObject)item).ObjectID.ObjectNumber == 5)
// Debug.WriteLine("items: " + ((PdfObject)item).ObjectID.ToString());
//if (pdfObject.ObjectNumber == 5)
// GetType();
#endif
IEnumerable enumerable = null; //(IEnumerator)pdfObject;
PdfDictionary dict;
PdfArray array;
if ((dict = pdfObject as PdfDictionary) != null)
enumerable = dict.Elements.Values;
else if ((array = pdfObject as PdfArray) != null)
enumerable = array.Elements;
else
Debug.Assert(false, "Should not come here.");
if (enumerable != null)
{
foreach (PdfItem item in enumerable)
{
PdfReference iref = item as PdfReference;
if (iref != null)
{
// Is this an indirect reference to an object that does not exist?
//if (iref.Document == null)
//{
// Debug.WriteLine("Dead object detected: " + iref.ObjectID.ToString());
// PdfReference dead = DeadObject;
// iref.ObjectID = dead.ObjectID;
// iref.Document = _document;
// iref.SetObject(dead.Value);
// PdfDictionary dict = (PdfDictionary)dead.Value;
// dict.Elements["/DeadObjectCount"] =
// new PdfInteger(dict.Elements.GetInteger("/DeadObjectCount") + 1);
// iref = dead;
//}
if (!ReferenceEquals(iref.Document, _document))
{
GetType();
Debug.WriteLine(String.Format("Bad iref: {0}", iref.ObjectID.ToString()));
}
Debug.Assert(ReferenceEquals(iref.Document, _document) || iref.Document == null, "External object detected!");
#if DEBUG_
if (iref.ObjectID.ObjectNumber == 23)
GetType();
#endif
if (!objects.ContainsKey(iref))
{
PdfObject value = iref.Value;
// Ignore unreachable objects.
if (iref.Document != null)
{
// ... from trailer hack
if (value == null)
{
iref = ObjectTable[iref.ObjectID];
Debug.Assert(iref.Value != null);
value = iref.Value;
}
Debug.Assert(ReferenceEquals(iref.Document, _document));
objects.Add(iref, null);
//Debug.WriteLine(String.Format("objects.Add('{0}', null);", iref.ObjectID.ToString()));
if (value is PdfArray || value is PdfDictionary)
TransitiveClosureImplementation(objects, value /*, ref depth*/);
}
//else
//{
// objects2.Add(this[iref.ObjectID], null);
//}
}
}
else
{
PdfObject pdfObject28 = item as PdfObject;
//if (pdfObject28 != null)
// Debug.Assert(Object.ReferenceEquals(pdfObject28.Document, _document));
if (pdfObject28 != null && (pdfObject28 is PdfDictionary || pdfObject28 is PdfArray))
TransitiveClosureImplementation(objects, pdfObject28 /*, ref depth*/);
}
}
}
}
finally
{
_nestingLevel--;
}
}
/// <summary>
/// Gets the cross reference to an objects used for undefined indirect references.
/// </summary>
public PdfReference DeadObject
{
get
{
if (_deadObject == null)
{
_deadObject = new PdfDictionary(_document);
Add(_deadObject);
_deadObject.Elements.Add("/DeadObjectCount", new PdfInteger());
}
return _deadObject.Reference;
}
}
PdfDictionary _deadObject;
}
///// <summary>
///// Represents the cross-reference table of a PDF document.
///// It contains all indirect objects of a document.
///// </summary>
//internal sealed class PdfCrossReferenceStreamTable // Must not be derive from PdfObject.
//{
// public PdfCrossReferenceStreamTable(PdfDocument document)
// {
// _document = document;
// }
// readonly PdfDocument _document;
// public class Item
// {
// public PdfReference Reference;
// public readonly List<CrossReferenceStreamEntry> Entries = new List<CrossReferenceStreamEntry>();
// }
//}
//struct CrossReferenceStreamEntry
//{
// public int Type;
// public int Field2;
// public int Field3;
//}
}

View File

@@ -0,0 +1,169 @@
#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;
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a base class for dictionaries with a content stream.
/// Implement IContentStream for use with a content writer.
/// </summary>
public abstract class PdfDictionaryWithContentStream : PdfDictionary, IContentStream
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfDictionaryWithContentStream"/> class.
/// </summary>
public PdfDictionaryWithContentStream()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="PdfDictionaryWithContentStream"/> class.
/// </summary>
/// <param name="document">The document.</param>
public PdfDictionaryWithContentStream(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Initializes a new instance from an existing dictionary. Used for object type transformation.
/// </summary>
protected PdfDictionaryWithContentStream(PdfDictionary dict)
: base(dict)
{ }
/// <summary>
/// Gets the resources dictionary of this dictionary. If no such dictionary exists, it is created.
/// </summary>
internal PdfResources Resources
{
get
{
if (_resources == null)
_resources = (PdfResources)Elements.GetValue(Keys.Resources, VCF.Create);
return _resources;
}
}
PdfResources _resources;
/// <summary>
/// Implements the interface because the primary function is internal.
/// </summary>
PdfResources IContentStream.Resources
{
get { return Resources; }
}
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);
}
internal string GetFontName(string idName, byte[] fontData, out PdfFont pdfFont)
{
pdfFont = _document.FontTable.GetFont(idName, fontData);
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 dictionary.
/// </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)
{
throw new NotImplementedException();
}
/// <summary>
/// Gets the resource name of the specified form within this dictionary.
/// </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)
{
throw new NotImplementedException();
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public class Keys : PdfDictionary.PdfStream.Keys
{
/// <summary>
/// (Optional but strongly recommended; PDF 1.2) A dictionary specifying any
/// resources (such as fonts and images) required by the form XObject.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResources))]
public const string Resources = "/Resources";
}
}
}

View File

@@ -0,0 +1,411 @@
#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.Globalization;
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
#endif
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents an extended graphics state object.
/// </summary>
public sealed class PdfExtGState : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfExtGState"/> class.
/// </summary>
/// <param name="document">The document.</param>
public PdfExtGState(PdfDocument document)
: base(document)
{
Elements.SetName(Keys.Type, "/ExtGState");
#if true_
//AIS false
//BM /Normal
//ca 1
//CA 1
//op false
//OP false
//OPM 1
//SA true
//SMask /None
//Type /ExtGState
Elements.SetValue(Keys.AIS, new PdfBoolean(false)); // The alpha source
Elements.SetName("/BM", "Normal");
Elements.SetValue(Keys.op, new PdfBoolean(false));
Elements.SetValue(Keys.OP, new PdfBoolean(false));
Elements.SetValue(Keys.OPM, new PdfInteger(1));
Elements.SetValue("/SA", new PdfBoolean(true));
Elements.SetName("/SMask", "None");
#endif
//#if OP_HACK
// Elements.SetValue(Keys.op, new PdfBoolean(false));
// Elements.SetValue(Keys.OP, new PdfBoolean(false));
// Elements.SetValue(Keys.OPM, new PdfInteger(1));
//#endif
}
/// <summary>
/// Used in Edf.Xps.
/// </summary>
internal void SetDefault1()
{
//<<
// /AIS false
// /BM /Normal
// /ca 1
// /CA 1
// /op false
// /OP false
// /OPM 1
// /SA true
// /SMask /None
// /Type /ExtGState
//>>
Elements.SetBoolean(Keys.AIS, false);
if (Elements.ContainsKey(Keys.BM)) Elements.SetName(Keys.BM, "/Normal");
StrokeAlpha = 1;
NonStrokeAlpha = 1;
Elements.SetBoolean(Keys.op, false);
Elements.SetBoolean(Keys.OP, false);
Elements.SetBoolean(Keys.SA, true);
Elements.SetName(Keys.SMask, "/None");
}
/// <summary>
/// Used in Edf.Xps.
/// ...for shading patterns
/// </summary>
internal void SetDefault2()
{
//<<
// /AIS false
// /BM /Normal
// /ca 1
// /CA 1
// /op true
// /OP true
// /OPM 1
// /SA true
// /SMask /None
// /Type /ExtGState
//>>
Elements.SetBoolean(Keys.AIS, false);
Elements.SetName(Keys.BM, "/Normal");
StrokeAlpha = 1;
NonStrokeAlpha = 1;
Elements.SetBoolean(Keys.op, true);
Elements.SetBoolean(Keys.OP, true);
Elements.SetInteger(Keys.OPM, 1);
Elements.SetBoolean(Keys.SA, true);
Elements.SetName(Keys.SMask, "/None");
}
/// <summary>
/// Sets the alpha value for stroking operations.
/// </summary>
public double StrokeAlpha
{
set
{
_strokeAlpha = value;
Elements.SetReal(Keys.CA, value);
UpdateKey();
}
}
double _strokeAlpha;
/// <summary>
/// Sets the alpha value for nonstroking operations.
/// </summary>
public double NonStrokeAlpha
{
set
{
_nonStrokeAlpha = value;
Elements.SetReal(Keys.ca, value);
UpdateKey();
}
}
double _nonStrokeAlpha;
/// <summary>
/// Sets the overprint value for stroking operations.
/// </summary>
public bool StrokeOverprint
{
set
{
_strokeOverprint = value;
Elements.SetBoolean(Keys.OP, value);
UpdateKey();
}
}
bool _strokeOverprint;
/// <summary>
/// Sets the overprint value for nonstroking operations.
/// </summary>
public bool NonStrokeOverprint
{
set
{
_nonStrokeOverprint = value;
Elements.SetBoolean(Keys.op, value);
UpdateKey();
}
}
bool _nonStrokeOverprint;
/// <summary>
/// Sets a soft mask object.
/// </summary>
public PdfSoftMask SoftMask
{
set { Elements.SetReference(Keys.SMask, value); }
}
internal string Key
{
get { return _key; }
}
void UpdateKey()
{
_key = ((int)(1000 * _strokeAlpha)).ToString(CultureInfo.InvariantCulture) +
((int)(1000 * _nonStrokeAlpha)).ToString(CultureInfo.InvariantCulture) +
(_strokeOverprint ? "S" : "s") + (_nonStrokeOverprint ? "N" : "n");
}
string _key;
internal static string MakeKey(double alpha, bool overPaint)
{
string key = ((int)(1000 * alpha)).ToString(CultureInfo.InvariantCulture) + (overPaint ? "O" : "0");
return key;
}
/// <summary>
/// Common keys for all streams.
/// </summary>
internal sealed class Keys : KeysBase
{
// ReSharper disable InconsistentNaming
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes;
/// must be ExtGState for a graphics state parameter dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Type = "/Type";
/// <summary>
/// (Optional; PDF 1.3) The line width (see <20>Line Width<74> on page 185).
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string LW = "/LW";
/// <summary>
/// (Optional; PDF 1.3) The line cap style.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string LC = "/LC";
/// <summary>
/// (Optional; PDF 1.3) The line join style.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string LJ = "/LJ";
/// <summary>
/// (Optional; PDF 1.3) The miter limit.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string ML = "/ML";
/// <summary>
/// (Optional; PDF 1.3) The line dash pattern, expressed as an array of the form
/// [dashArray dashPhase], where dashArray is itself an array and dashPhase is an integer.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string D = "/D";
/// <summary>
/// (Optional; PDF 1.3) The name of the rendering intent.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string RI = "/RI";
/// <summary>
/// (Optional) A flag specifying whether to apply overprint. In PDF 1.2 and earlier,
/// there is a single overprint parameter that applies to all painting operations.
/// Beginning with PDF 1.3, there are two separate overprint parameters: one for stroking
/// and one for all other painting operations. Specifying an OP entry sets both parameters
/// unless there is also an op entry in the same graphics state parameter dictionary, in
/// which case the OP entry sets only the overprint parameter for stroking.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string OP = "/OP";
/// <summary>
/// (Optional; PDF 1.3) A flag specifying whether to apply overprint for painting operations
/// other than stroking. If this entry is absent, the OP entry, if any, sets this parameter.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string op = "/op";
/// <summary>
/// (Optional; PDF 1.3) The overprint mode.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string OPM = "/OPM";
/// <summary>
/// (Optional; PDF 1.3) An array of the form [font size], where font is an indirect
/// reference to a font dictionary and size is a number expressed in text space units.
/// These two objects correspond to the operands of the Tf operator; however,
/// the first operand is an indirect object reference instead of a resource name.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Font = "/Font";
/// <summary>
/// (Optional) The black-generation function, which maps the interval [0.0 1.0]
/// to the interval [0.0 1.0].
/// </summary>
[KeyInfo(KeyType.Function | KeyType.Optional)]
public const string BG = "/BG";
/// <summary>
/// (Optional; PDF 1.3) Same as BG except that the value may also be the name Default,
/// denoting the black-generation function that was in effect at the start of the page.
/// If both BG and BG2 are present in the same graphics state parameter dictionary,
/// BG2 takes precedence.
/// </summary>
[KeyInfo(KeyType.FunctionOrName | KeyType.Optional)]
public const string BG2 = "/BG2";
/// <summary>
/// (Optional) The undercolor-removal function, which maps the interval
/// [0.0 1.0] to the interval [-1.0 1.0].
/// </summary>
[KeyInfo(KeyType.Function | KeyType.Optional)]
public const string UCR = "/UCR";
/// <summary>
/// (Optional; PDF 1.3) Same as UCR except that the value may also be the name Default,
/// denoting the undercolor-removal function that was in effect at the start of the page.
/// If both UCR and UCR2 are present in the same graphics state parameter dictionary,
/// UCR2 takes precedence.
/// </summary>
[KeyInfo(KeyType.FunctionOrName | KeyType.Optional)]
public const string UCR2 = "/UCR2";
//TR function, array, or name
//TR2 function, array, or name
//HT dictionary, stream, or name
//FL number
//SM number
/// <summary>
/// (Optional) A flag specifying whether to apply automatic stroke adjustment.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string SA = "/SA";
/// <summary>
/// (Optional; PDF 1.4) The current blend mode to be used in the transparent imaging model.
/// </summary>
[KeyInfo(KeyType.NameOrArray | KeyType.Optional)]
public const string BM = "/BM";
/// <summary>
/// (Optional; PDF 1.4) The current soft mask, specifying the mask shape or
/// mask opacity values to be used in the transparent imaging model.
/// </summary>
[KeyInfo(KeyType.NameOrDictionary | KeyType.Optional)]
public const string SMask = "/SMask";
/// <summary>
/// (Optional; PDF 1.4) The current stroking alpha constant, specifying the constant
/// shape or constant opacity value to be used for stroking operations in the transparent
/// imaging model.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string CA = "/CA";
/// <summary>
/// (Optional; PDF 1.4) Same as CA, but for nonstroking operations.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string ca = "/ca";
/// <summary>
/// (Optional; PDF 1.4) The alpha source flag (<28>alpha is shape<70>), specifying whether
/// the current soft mask and alpha constant are to be interpreted as shape values (true)
/// or opacity values (false).
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string AIS = "/AIS";
/// <summary>
/// (Optional; PDF 1.4) The text knockout flag, which determines the behavior of
/// overlapping glyphs within a text object in the transparent imaging model.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string TK = "/TK";
// ReSharper restore InconsistentNaming
/// <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; }
}
}
}

View File

@@ -0,0 +1,95 @@
#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.Collections.Generic;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Contains all used ExtGState objects of a document.
/// </summary>
public sealed class PdfExtGStateTable : PdfResourceTable
{
/// <summary>
/// Initializes a new instance of this class, which is a singleton for each document.
/// </summary>
public PdfExtGStateTable(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Gets a PdfExtGState with the key 'CA' set to the specified alpha value.
/// </summary>
public PdfExtGState GetExtGStateStroke(double alpha, bool overprint)
{
string key = PdfExtGState.MakeKey(alpha, overprint);
PdfExtGState extGState;
if (!_strokeAlphaValues.TryGetValue(key, out extGState))
{
extGState = new PdfExtGState(Owner);
//extGState.Elements[PdfExtGState.Keys.CA] = new PdfReal(alpha);
extGState.StrokeAlpha = alpha;
if (overprint)
{
extGState.StrokeOverprint = true;
extGState.Elements.SetInteger(PdfExtGState.Keys.OPM, 1);
}
_strokeAlphaValues[key] = extGState;
}
return extGState;
}
/// <summary>
/// Gets a PdfExtGState with the key 'ca' set to the specified alpha value.
/// </summary>
public PdfExtGState GetExtGStateNonStroke(double alpha, bool overprint)
{
string key = PdfExtGState.MakeKey(alpha, overprint);
PdfExtGState extGState;
if (!_nonStrokeStates.TryGetValue(key, out extGState))
{
extGState = new PdfExtGState(Owner);
//extGState.Elements[PdfExtGState.Keys.ca] = new PdfReal(alpha);
extGState.NonStrokeAlpha = alpha;
if (overprint)
{
extGState.NonStrokeOverprint = true;
extGState.Elements.SetInteger(PdfExtGState.Keys.OPM, 1);
}
_nonStrokeStates[key] = extGState;
}
return extGState;
}
readonly Dictionary<string, PdfExtGState> _strokeAlphaValues = new Dictionary<string, PdfExtGState>();
readonly Dictionary<string, PdfExtGState> _nonStrokeStates = new Dictionary<string, PdfExtGState>();
}
}

View File

@@ -0,0 +1,156 @@
#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.Text;
using PdfSharp.Fonts;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF font.
/// </summary>
public class PdfFont : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfFont"/> class.
/// </summary>
public PdfFont(PdfDocument document)
: base(document)
{ }
internal PdfFontDescriptor FontDescriptor
{
get
{
Debug.Assert(_fontDescriptor != null);
return _fontDescriptor;
}
set { _fontDescriptor = value; }
}
PdfFontDescriptor _fontDescriptor;
internal PdfFontEncoding FontEncoding;
/// <summary>
/// Gets a value indicating whether this instance is symbol font.
/// </summary>
public bool IsSymbolFont
{
get { return _fontDescriptor.IsSymbolFont; }
}
internal void AddChars(string text)
{
if (_cmapInfo != null)
_cmapInfo.AddChars(text);
}
internal void AddGlyphIndices(string glyphIndices)
{
if (_cmapInfo != null)
_cmapInfo.AddGlyphIndices(glyphIndices);
}
/// <summary>
/// Gets or sets the CMapInfo.
/// </summary>
internal CMapInfo CMapInfo
{
get { return _cmapInfo; }
set { _cmapInfo = value; }
}
internal CMapInfo _cmapInfo;
/// <summary>
/// Gets or sets ToUnicodeMap.
/// </summary>
internal PdfToUnicodeMap ToUnicodeMap
{
get { return _toUnicode; }
set { _toUnicode = value; }
}
internal PdfToUnicodeMap _toUnicode;
/// <summary>
/// Adds a tag of exactly six uppercase letters to the font name
/// according to PDF Reference Section 5.5.3 'Font Subsets'
/// </summary>
internal static string CreateEmbeddedFontSubsetName(string name)
{
StringBuilder s = new StringBuilder(64);
byte[] bytes = Guid.NewGuid().ToByteArray();
for (int idx = 0; idx < 6; idx++)
s.Append((char)('A' + bytes[idx] % 26));
s.Append('+');
if (name.StartsWith("/"))
s.Append(name.Substring(1));
else
s.Append(name);
return s.ToString();
}
/// <summary>
/// Predefined keys common to all font dictionaries.
/// </summary>
public class Keys : KeysBase
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Font for a font dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Font")]
public const string Type = "/Type";
/// <summary>
/// (Required) The type of font.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string Subtype = "/Subtype";
/// <summary>
/// (Required) The PostScript name of the font.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string BaseFont = "/BaseFont";
/// <summary>
/// (Required except for the standard 14 fonts; must be an indirect reference)
/// A font descriptor describing the font<6E>s metrics other than its glyph widths.
/// Note: For the standard 14 fonts, the entries FirstChar, LastChar, Widths, and
/// FontDescriptor must either all be present or all be absent. Ordinarily, they are
/// absent; specifying them enables a standard font to be overridden.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.MustBeIndirect, typeof(PdfFontDescriptor))]
public const string FontDescriptor = "/FontDescriptor";
}
}
}

View File

@@ -0,0 +1,351 @@
#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.Fonts.OpenType;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// The PDF font descriptor flags.
/// </summary>
[Flags]
enum PdfFontDescriptorFlags
{
/// <summary>
/// All glyphs have the same width (as opposed to proportional or variable-pitch
/// fonts, which have different widths).
/// </summary>
FixedPitch = 1 << 0,
/// <summary>
/// Glyphs have serifs, which are short strokes drawn at an angle on the top and
/// bottom of glyph stems. (Sans serif fonts do not have serifs.)
/// </summary>
Serif = 1 << 1,
/// <summary>
/// Font contains glyphs outside the Adobe standard Latin character set. This
/// flag and the Nonsymbolic flag cannot both be set or both be clear.
/// </summary>
Symbolic = 1 << 2,
/// <summary>
/// Glyphs resemble cursive handwriting.
/// </summary>
Script = 1 << 3,
/// <summary>
/// Font uses the Adobe standard Latin character set or a subset of it.
/// </summary>
Nonsymbolic = 1 << 5,
/// <summary>
/// Glyphs have dominant vertical strokes that are slanted.
/// </summary>
Italic = 1 << 6,
/// <summary>
/// Font contains no lowercase letters; typically used for display purposes,
/// such as for titles or headlines.
/// </summary>
AllCap = 1 << 16,
/// <summary>
/// Font contains both uppercase and lowercase letters. The uppercase letters are
/// similar to those in the regular version of the same typeface family. The glyphs
/// for the lowercase letters have the same shapes as the corresponding uppercase
/// letters, but they are sized and their proportions adjusted so that they have the
/// same size and stroke weight as lowercase glyphs in the same typeface family.
/// </summary>
SmallCap = 1 << 17,
/// <summary>
/// Determines whether bold glyphs are painted with extra pixels even at very small
/// text sizes.
/// </summary>
ForceBold = 1 << 18,
}
/// <summary>
/// A PDF font descriptor specifies metrics and other attributes of a simple font,
/// as distinct from the metrics of individual glyphs.
/// </summary>
public sealed class PdfFontDescriptor : PdfDictionary
{
internal PdfFontDescriptor(PdfDocument document, OpenTypeDescriptor descriptor)
: base(document)
{
_descriptor = descriptor;
Elements.SetName(Keys.Type, "/FontDescriptor");
Elements.SetInteger(Keys.Ascent, _descriptor.DesignUnitsToPdf(_descriptor.Ascender));
Elements.SetInteger(Keys.CapHeight, _descriptor.DesignUnitsToPdf(_descriptor.CapHeight));
Elements.SetInteger(Keys.Descent, _descriptor.DesignUnitsToPdf(_descriptor.Descender));
Elements.SetInteger(Keys.Flags, (int)FlagsFromDescriptor(_descriptor));
Elements.SetRectangle(Keys.FontBBox, new PdfRectangle(
_descriptor.DesignUnitsToPdf(_descriptor.XMin),
_descriptor.DesignUnitsToPdf(_descriptor.YMin),
_descriptor.DesignUnitsToPdf(_descriptor.XMax),
_descriptor.DesignUnitsToPdf(_descriptor.YMax)));
// not here, done in PdfFont later...
//Elements.SetName(Keys.FontName, "abc"); //descriptor.FontName);
Elements.SetReal(Keys.ItalicAngle, _descriptor.ItalicAngle);
Elements.SetInteger(Keys.StemV, _descriptor.StemV);
Elements.SetInteger(Keys.XHeight, _descriptor.DesignUnitsToPdf(_descriptor.XHeight));
}
//HACK OpenTypeDescriptor descriptor
internal OpenTypeDescriptor _descriptor;
/// <summary>
/// Gets or sets the name of the font.
/// </summary>
public string FontName
{
get { return Elements.GetName(Keys.FontName); }
set { Elements.SetName(Keys.FontName, value); }
}
/// <summary>
/// Gets a value indicating whether this instance is symbol font.
/// </summary>
public bool IsSymbolFont
{
get { return _isSymbolFont; }
}
bool _isSymbolFont;
// HACK FlagsFromDescriptor(OpenTypeDescriptor descriptor)
PdfFontDescriptorFlags FlagsFromDescriptor(OpenTypeDescriptor descriptor)
{
PdfFontDescriptorFlags flags = 0;
_isSymbolFont = descriptor.FontFace.cmap.symbol;
flags |= descriptor.FontFace.cmap.symbol ? PdfFontDescriptorFlags.Symbolic : PdfFontDescriptorFlags.Nonsymbolic;
return flags;
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public sealed class Keys : KeysBase
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes; must be
/// FontDescriptor for a font descriptor.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "FontDescriptor")]
public const string Type = "/Type";
/// <summary>
/// (Required) The PostScript name of the font. This name should be the same as the
/// value of BaseFont in the font or CIDFont dictionary that refers to this font descriptor.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string FontName = "/FontName";
/// <summary>
/// (Optional; PDF 1.5; strongly recommended for Type 3 fonts in Tagged PDF documents)
/// A string specifying the preferred font family name. For example, for the font
/// Times Bold Italic, the FontFamily is Times.
/// </summary>
[KeyInfo(KeyType.String | KeyType.Optional)]
public const string FontFamily = "/FontFamily";
/// <summary>
/// (Optional; PDF 1.5; strongly recommended for Type 3 fonts in Tagged PDF documents)
/// The font stretch value. It must be one of the following names (ordered from
/// narrowest to widest): UltraCondensed, ExtraCondensed, Condensed, SemiCondensed,
/// Normal, SemiExpanded, Expanded, ExtraExpanded or UltraExpanded.
/// Note: The specific interpretation of these values varies from font to font.
/// For example, Condensed in one font may appear most similar to Normal in another.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string FontStretch = "/FontStretch";
/// <summary>
/// (Optional; PDF 1.5; strongly recommended for Type 3 fonts in Tagged PDF documents)
/// The weight (thickness) component of the fully-qualified font name or font specifier.
/// The possible values are 100, 200, 300, 400, 500, 600, 700, 800, or 900, where each
/// number indicates a weight that is at least as dark as its predecessor. A value of
/// 400 indicates a normal weight; 700 indicates bold.
/// Note: The specific interpretation of these values varies from font to font.
/// For example, 300 in one font may appear most similar to 500 in another.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string FontWeight = "/FontWeight";
/// <summary>
/// (Required) A collection of flags defining various characteristics of the font.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string Flags = "/Flags";
/// <summary>
/// (Required, except for Type 3 fonts) A rectangle (see Section 3.8.4, <20>Rectangles<65>),
/// expressed in the glyph coordinate system, specifying the font bounding box. This
/// is the smallest rectangle enclosing the shape that would result if all of the
/// glyphs of the font were placed with their origins coincident and then filled.
/// </summary>
[KeyInfo(KeyType.Rectangle | KeyType.Required)]
public const string FontBBox = "/FontBBox";
/// <summary>
/// (Required) The angle, expressed in degrees counterclockwise from the vertical, of
/// the dominant vertical strokes of the font. (For example, the 9-o<>clock position is 90
/// degrees, and the 3-o<>clock position is <20>90 degrees.) The value is negative for fonts
/// that slope to the right, as almost all italic fonts do.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string ItalicAngle = "/ItalicAngle";
/// <summary>
/// (Required, except for Type 3 fonts) The maximum height above the baseline reached
/// by glyphs in this font, excluding the height of glyphs for accented characters.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string Ascent = "/Ascent";
/// <summary>
/// (Required, except for Type 3 fonts) The maximum depth below the baseline reached
/// by glyphs in this font. The value is a negative number.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string Descent = "/Descent";
/// <summary>
/// (Optional) The spacing between baselines of consecutive lines of text.
/// Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string Leading = "/Leading";
/// <summary>
/// (Required for fonts that have Latin characters, except for Type 3 fonts) The vertical
/// coordinate of the top of flat capital letters, measured from the baseline.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string CapHeight = "/CapHeight";
/// <summary>
/// (Optional) The font<6E>s x height: the vertical coordinate of the top of flat nonascending
/// lowercase letters (like the letter x), measured from the baseline, in fonts that have
/// Latin characters. Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string XHeight = "/XHeight";
/// <summary>
/// (Required, except for Type 3 fonts) The thickness, measured horizontally, of the dominant
/// vertical stems of glyphs in the font.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string StemV = "/StemV";
/// <summary>
/// (Optional) The thickness, measured vertically, of the dominant horizontal stems
/// of glyphs in the font. Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string StemH = "/StemH";
/// <summary>
/// (Optional) The average width of glyphs in the font. Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string AvgWidth = "/AvgWidth";
/// <summary>
/// (Optional) The maximum width of glyphs in the font. Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string MaxWidth = "/MaxWidth";
/// <summary>
/// (Optional) The width to use for character codes whose widths are not specified in a
/// font dictionary<72>s Widths array. This has a predictable effect only if all such codes
/// map to glyphs whose actual widths are the same as the value of the MissingWidth entry.
/// Default value: 0.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Optional)]
public const string MissingWidth = "/MissingWidth";
/// <summary>
/// (Optional) A stream containing a Type 1 font program.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string FontFile = "/FontFile";
/// <summary>
/// (Optional; PDF 1.1) A stream containing a TrueType font program.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string FontFile2 = "/FontFile2";
/// <summary>
/// (Optional; PDF 1.2) A stream containing a font program whose format is specified
/// by the Subtype entry in the stream dictionary.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string FontFile3 = "/FontFile3";
/// <summary>
/// (Optional; meaningful only in Type 1 fonts; PDF 1.1) A string listing the character
/// names defined in a font subset. The names in this string must be in PDF syntax<61>that is,
/// each name preceded by a slash (/). The names can appear in any order. The name .notdef
/// should be omitted; it is assumed to exist in the font subset. If this entry is absent,
/// the only indication of a font subset is the subset tag in the FontName entry.
/// </summary>
[KeyInfo(KeyType.String | KeyType.Optional)]
public const string CharSet = "/CharSet";
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static DictionaryMeta Meta
{
get
{
if (_meta == null)
_meta = CreateMeta(typeof(Keys));
return _meta;
}
}
static DictionaryMeta _meta;
}
/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}

View File

@@ -0,0 +1,143 @@
#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.Diagnostics;
using System.Collections.Generic;
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
internal enum FontType
{
/// <summary>
/// TrueType with WinAnsi encoding.
/// </summary>
TrueType = 1,
/// <summary>
/// TrueType with Identity-H or Identity-V encoding (unicode).
/// </summary>
Type0 = 2,
}
/// <summary>
/// Contains all used fonts of a document.
/// </summary>
internal sealed class PdfFontTable : PdfResourceTable
{
/// <summary>
/// Initializes a new instance of this class, which is a singleton for each document.
/// </summary>
public PdfFontTable(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Gets a PdfFont from an XFont. If no PdfFont already exists, a new one is created.
/// </summary>
public PdfFont GetFont(XFont font)
{
string selector = font.Selector;
if (selector == null)
{
selector = ComputeKey(font); //new FontSelector(font);
font.Selector = selector;
}
PdfFont pdfFont;
if (!_fonts.TryGetValue(selector, out pdfFont))
{
if (font.Unicode)
pdfFont = new PdfType0Font(Owner, font, font.IsVertical);
else
pdfFont = new PdfTrueTypeFont(Owner, font);
//pdfFont.Document = _document;
Debug.Assert(pdfFont.Owner == Owner);
_fonts[selector] = pdfFont;
}
return pdfFont;
}
#if true
/// <summary>
/// Gets a PdfFont from a font program. If no PdfFont already exists, a new one is created.
/// </summary>
public PdfFont GetFont(string idName, byte[] fontData)
{
Debug.Assert(false);
//FontSelector selector = new FontSelector(idName);
string selector = null; // ComputeKey(font); //new FontSelector(font);
PdfFont pdfFont;
if (!_fonts.TryGetValue(selector, out pdfFont))
{
//if (font.Unicode)
pdfFont = new PdfType0Font(Owner, idName, fontData, false);
//else
// pdfFont = new PdfTrueTypeFont(_owner, font);
//pdfFont.Document = _document;
Debug.Assert(pdfFont.Owner == Owner);
_fonts[selector] = pdfFont;
}
return pdfFont;
}
#endif
/// <summary>
/// Tries to gets a PdfFont from the font dictionary.
/// Returns null if no such PdfFont exists.
/// </summary>
public PdfFont TryGetFont(string idName)
{
Debug.Assert(false);
//FontSelector selector = new FontSelector(idName);
string selector = null;
PdfFont pdfFont;
_fonts.TryGetValue(selector, out pdfFont);
return pdfFont;
}
internal static string ComputeKey(XFont font)
{
XGlyphTypeface glyphTypeface = font.GlyphTypeface;
string key = glyphTypeface.Fontface.FullFaceName.ToLowerInvariant() +
(glyphTypeface.IsBold ? "/b" : "") + (glyphTypeface.IsItalic ? "/i" : "") + font.Unicode;
return key;
}
/// <summary>
/// Map from PdfFontSelector to PdfFont.
/// </summary>
readonly Dictionary<string, PdfFont> _fonts = new Dictionary<string, PdfFont>();
public void PrepareForSave()
{
foreach (PdfFont font in _fonts.Values)
font.PrepareForSave();
}
}
}

View File

@@ -0,0 +1,509 @@
#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;
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents an external form object (e.g. an imported page).
/// </summary>
public sealed class PdfFormXObject : PdfXObject, IContentStream
{
internal PdfFormXObject(PdfDocument thisDocument)
: base(thisDocument)
{
Elements.SetName(Keys.Type, "/XObject");
Elements.SetName(Keys.Subtype, "/Form");
}
internal PdfFormXObject(PdfDocument thisDocument, XForm form)
: base(thisDocument)
{
// BUG: form is not used
Elements.SetName(Keys.Type, "/XObject");
Elements.SetName(Keys.Subtype, "/Form");
//if (form.IsTemplate)
//{ }
}
internal double DpiX
{
get { return _dpiX; }
set { _dpiX = value; }
}
double _dpiX = 72;
internal double DpiY
{
get { return _dpiY; }
set { _dpiY = value; }
}
double _dpiY = 72;
internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
: base(thisDocument)
{
Debug.Assert(importedObjectTable != null);
Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner));
Elements.SetName(Keys.Type, "/XObject");
Elements.SetName(Keys.Subtype, "/Form");
if (form.IsTemplate)
{
Debug.Assert(importedObjectTable == null);
// TODO more initialization here???
return;
}
XPdfForm pdfForm = form;
// Get import page
PdfPages importPages = importedObjectTable.ExternalDocument.Pages;
if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path);
PdfPage importPage = importPages[pdfForm.PageNumber - 1];
// Import resources
PdfItem res = importPage.Elements["/Resources"];
if (res != null) // unlikely but possible
{
#if true
// Get root object
PdfObject root;
if (res is PdfReference)
root = ((PdfReference)res).Value;
else
root = (PdfDictionary)res;
root = ImportClosure(importedObjectTable, thisDocument, root);
// If the root was a direct object, make it indirect.
if (root.Reference == null)
thisDocument._irefTable.Add(root);
Debug.Assert(root.Reference != null);
Elements["/Resources"] = root.Reference;
#else
// Get transitive closure
PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
int count = resources.Length;
#if DEBUG_
for (int idx = 0; idx < count; idx++)
{
Debug.Assert(resources[idx].XRef != null);
Debug.Assert(resources[idx].XRef.Document != null);
Debug.Assert(resources[idx].Document != null);
if (resources[idx].ObjectID.ObjectNumber == 12)
GetType();
}
#endif
// 1st step. Already imported objects are reused and new ones are cloned.
for (int idx = 0; idx < count; idx++)
{
PdfObject obj = resources[idx];
if (importedObjectTable.Contains(obj.ObjectID))
{
// external object was already imported
PdfReference iref = importedObjectTable[obj.ObjectID];
Debug.Assert(iref != null);
Debug.Assert(iref.Value != null);
Debug.Assert(iref.Document == Owner);
// replace external object by the already clone counterpart
resources[idx] = iref.Value;
}
else
{
// External object was not imported earlier and must be cloned
PdfObject clone = obj.Clone();
Debug.Assert(clone.Reference == null);
clone.Document = Owner;
if (obj.Reference != null)
{
// add it to this (the importer) document
Owner.irefTable.Add(clone);
Debug.Assert(clone.Reference != null);
// save old object identifier
importedObjectTable.Add(obj.ObjectID, clone.Reference);
//Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
}
else
{
// The root object (the /Resources value) is not an indirect object
Debug.Assert(idx == 0);
// add it to this (the importer) document
Owner.irefTable.Add(clone);
Debug.Assert(clone.Reference != null);
}
// replace external object by its clone
resources[idx] = clone;
}
}
#if DEBUG_
for (int idx = 0; idx < count; idx++)
{
Debug.Assert(resources[idx].XRef != null);
Debug.Assert(resources[idx].XRef.Document != null);
Debug.Assert(resources[idx].Document != null);
if (resources[idx].ObjectID.ObjectNumber == 12)
GetType();
}
#endif
// 2nd step. Fix up indirect references that still refers to the import document.
for (int idx = 0; idx < count; idx++)
{
PdfObject obj = resources[idx];
Debug.Assert(obj.Owner != null);
FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
}
// Set resources key to the root of the clones
Elements["/Resources"] = resources[0].Reference;
#endif
}
// Take /Rotate into account.
PdfRectangle rect = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
// Reduce rotation to 0, 90, 180, or 270.
int rotate = (importPage.Elements.GetInteger(PdfPage.Keys.Rotate) % 360 + 360) % 360;
//rotate = 0;
if (rotate == 0)
{
// Set bounding box to media box.
Elements["/BBox"] = rect;
}
else
{
// TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
Elements["/BBox"] = rect;
// Rotate the image such that it is upright.
XMatrix matrix = new XMatrix();
double width = rect.Width;
double height = rect.Height;
matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));
// Translate the image such that its center lies on the center of the rotated bounding box.
double offset = (height - width) / 2;
if (rotate == 90)
{
// TODO It seems we can simplify this as the sign of offset changes too.
if (height > width)
matrix.TranslatePrepend(offset, offset); // Tested.
else
matrix.TranslatePrepend(offset, offset); // TODO Test case.
}
else if (rotate == 270)
{
// TODO It seems we can simplify this as the sign of offset changes too.
if (height > width)
matrix.TranslatePrepend(-offset, -offset); // Tested.
else
matrix.TranslatePrepend(-offset, -offset); // Tested.
}
//string item = "[" + PdfEncoders.ToString(matrix) + "]";
//Elements[Keys.Matrix] = new PdfLiteral(item);
Elements.SetMatrix(Keys.Matrix, matrix);
}
// Preserve filter because the content keeps unmodified.
PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
content.Compressed = true;
#endif
PdfItem filter = content.Elements["/Filter"];
if (filter != null)
Elements["/Filter"] = filter.Clone();
// (no cloning needed because the bytes keep untouched)
Stream = content.Stream; // new PdfStream(bytes, this);
Elements.SetInteger("/Length", content.Stream.Value.Length);
}
/// <summary>
/// Gets the PdfResources object of this form.
/// </summary>
public PdfResources Resources
{
get
{
if (_resources == null)
_resources = (PdfResources)Elements.GetValue(Keys.Resources, VCF.Create);
return _resources;
}
}
PdfResources _resources;
PdfResources IContentStream.Resources
{
get { return Resources; }
}
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>
/// Gets the resource name of the specified font data within this form XObject.
/// </summary>
internal string GetFontName(string idName, byte[] fontData, out PdfFont pdfFont)
{
pdfFont = _document.FontTable.GetFont(idName, fontData);
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);
}
string IContentStream.GetImageName(XImage image)
{
throw new NotImplementedException();
}
string IContentStream.GetFormName(XForm form)
{
throw new NotImplementedException();
}
#if keep_code_some_time_as_reference
/// <summary>
/// Replace all indirect references to external objects by their cloned counterparts
/// owned by the importer document.
/// </summary>
void FixUpObject_old(PdfImportedObjectTable iot, PdfObject value)
{
// TODO: merge with PdfXObject.FixUpObject
PdfDictionary dict;
PdfArray array;
if ((dict = value as PdfDictionary) != null)
{
// Set document for cloned direct objects
if (dict.Owner == null)
dict.Document = Owner;
else
Debug.Assert(dict.Owner == Owner);
// Search for indirect references in all keys
PdfName[] names = dict.Elements.KeyNames;
foreach (PdfName name in names)
{
PdfItem item = dict.Elements[name];
// Is item an iref?
PdfReference iref = item as PdfReference;
if (iref != null)
{
// Does the iref already belong to this document?
if (iref.Document == Owner)
{
// Yes: fine
continue;
}
else
{
Debug.Assert(iref.Document == iot.ExternalDocument);
// No: replace with iref of cloned object
PdfReference newXRef = iot[iref.ObjectID];
Debug.Assert(newXRef != null);
Debug.Assert(newXRef.Document == Owner);
dict.Elements[name] = newXRef;
}
}
else if (item is PdfObject)
{
// Fix up inner objects
FixUpObject_old(iot, (PdfObject)item);
}
}
}
else if ((array = value as PdfArray) != null)
{
// Set document for cloned direct objects
if (array.Owner == null)
array.Document = Owner;
else
Debug.Assert(array.Owner == Owner);
// Search for indirect references in all array elements
int count = array.Elements.Count;
for (int idx = 0; idx < count; idx++)
{
PdfItem item = array.Elements[idx];
// Is item an iref?
PdfReference iref = item as PdfReference;
if (iref != null)
{
// Does the iref belongs to this document?
if (iref.Document == Owner)
{
// Yes: fine
continue;
}
else
{
Debug.Assert(iref.Document == iot.ExternalDocument);
// No: replace with iref of cloned object
PdfReference newXRef = iot[iref.ObjectID];
Debug.Assert(newXRef != null);
Debug.Assert(newXRef.Document == Owner);
array.Elements[idx] = newXRef;
}
}
else if (item is PdfObject)
{
// Fix up inner objects
FixUpObject_old(iot, (PdfObject)item);
}
}
}
}
#endif
// /// <summary>
// /// Returns ???
// /// </summary>
// public override string ToString()
// {
// return "Form";
// }
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public sealed new class Keys : PdfXObject.Keys
{
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes; if present,
/// must be XObject for a form XObject.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Type = "/Type";
/// <summary>
/// (Required) The type of XObject that this dictionary describes; must be Form
/// for a form XObject.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string Subtype = "/Subtype";
/// <summary>
/// (Optional) A code identifying the type of form XObject that this dictionary
/// describes. The only valid value defined at the time of publication is 1.
/// Default value: 1.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string FormType = "/FormType";
/// <summary>
/// (Required) An array of four numbers in the form coordinate system, giving the
/// coordinates of the left, bottom, right, and top edges, respectively, of the
/// form XObject<63>s bounding box. These boundaries are used to clip the form XObject
/// and to determine its size for caching.
/// </summary>
[KeyInfo(KeyType.Rectangle | KeyType.Required)]
public const string BBox = "/BBox";
/// <summary>
/// (Optional) An array of six numbers specifying the form matrix, which maps
/// form space into user space.
/// Default value: the identity matrix [1 0 0 1 0 0].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Matrix = "/Matrix";
/// <summary>
/// (Optional but strongly recommended; PDF 1.2) A dictionary specifying any
/// resources (such as fonts and images) required by the form XObject.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResources))]
public const string Resources = "/Resources";
/// <summary>
/// (Optional; PDF 1.4) A group attributes dictionary indicating that the contents
/// of the form XObject are to be treated as a group and specifying the attributes
/// of that group (see Section 4.9.2, <20>Group XObjects<74>).
/// Note: If a Ref entry (see below) is present, the group attributes also apply to the
/// external page imported by that entry, which allows such an imported page to be
/// treated as a group without further modification.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string Group = "/Group";
// further keys:
//Ref
//Metadata
//PieceInfo
//LastModified
//StructParent
//StructParents
//OPI
//OC
//Name
/// <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; }
}
}
}

View File

@@ -0,0 +1,228 @@
#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.Collections.Generic;
using System.Globalization;
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Contains all external PDF files from which PdfFormXObjects are imported into the current document.
/// </summary>
internal sealed class PdfFormXObjectTable : PdfResourceTable
{
// The name PdfFormXObjectTable is technically not correct, because in contrast to PdfFontTable
// or PdfImageTable this class holds no PdfFormXObject objects. Actually it holds instances of
// the class ImportedObjectTable, one for each external document. The PdfFormXObject instances
// are not cached, because they hold a transformation matrix that make them unique. If the user
// wants to use a particual page of a PdfFormXObject more than once, he must reuse the object
// before he changes the PageNumber or the transformation matrix. In other words this class
// caches the indirect objects of an external form, not the form itself.
/// <summary>
/// Initializes a new instance of this class, which is a singleton for each document.
/// </summary>
public PdfFormXObjectTable(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Gets a PdfFormXObject from an XPdfForm. Because the returned objects must be unique, always
/// a new instance of PdfFormXObject is created if none exists for the specified form.
/// </summary>
public PdfFormXObject GetForm(XForm form)
{
// If the form already has a PdfFormXObject, return it.
if (form._pdfForm != null)
{
Debug.Assert(form.IsTemplate, "An XPdfForm must not have a PdfFormXObject.");
if (ReferenceEquals(form._pdfForm.Owner, Owner))
return form._pdfForm;
//throw new InvalidOperationException("Because of a current limitation of PDFsharp an XPdfForm object can be used only within one single PdfDocument.");
// Dispose PdfFromXObject when document has changed
form._pdfForm = null;
}
XPdfForm pdfForm = form as XPdfForm;
if (pdfForm != null)
{
// Is the external PDF file from which is imported already known for the current document?
Selector selector = new Selector(form);
PdfImportedObjectTable importedObjectTable;
if (!_forms.TryGetValue(selector, out importedObjectTable))
{
// No: Get the external document from the form and create ImportedObjectTable.
PdfDocument doc = pdfForm.ExternalDocument;
importedObjectTable = new PdfImportedObjectTable(Owner, doc);
_forms[selector] = importedObjectTable;
}
PdfFormXObject xObject = importedObjectTable.GetXObject(pdfForm.PageNumber);
if (xObject == null)
{
xObject = new PdfFormXObject(Owner, importedObjectTable, pdfForm);
importedObjectTable.SetXObject(pdfForm.PageNumber, xObject);
}
return xObject;
}
Debug.Assert(form.GetType() == typeof(XForm));
form._pdfForm = new PdfFormXObject(Owner, form);
return form._pdfForm;
}
/// <summary>
/// Gets the imported object table.
/// </summary>
public PdfImportedObjectTable GetImportedObjectTable(PdfPage page)
{
// Is the external PDF file from which is imported already known for the current document?
Selector selector = new Selector(page);
PdfImportedObjectTable importedObjectTable;
if (!_forms.TryGetValue(selector, out importedObjectTable))
{
importedObjectTable = new PdfImportedObjectTable(Owner, page.Owner);
_forms[selector] = importedObjectTable;
}
return importedObjectTable;
}
/// <summary>
/// Gets the imported object table.
/// </summary>
public PdfImportedObjectTable GetImportedObjectTable(PdfDocument document)
{
if (document == null)
throw new ArgumentNullException("document");
// Is the external PDF file from which is imported already known for the current document?
Selector selector = new Selector(document);
PdfImportedObjectTable importedObjectTable;
if (!_forms.TryGetValue(selector, out importedObjectTable))
{
// Create new table for document.
importedObjectTable = new PdfImportedObjectTable(Owner, document);
_forms[selector] = importedObjectTable;
}
return importedObjectTable;
}
public void DetachDocument(PdfDocument.DocumentHandle handle)
{
if (handle.IsAlive)
{
foreach (Selector selector in _forms.Keys)
{
PdfImportedObjectTable table = _forms[selector];
if (table.ExternalDocument != null && table.ExternalDocument.Handle == handle)
{
_forms.Remove(selector);
break;
}
}
}
// Clean table
bool itemRemoved = true;
while (itemRemoved)
{
itemRemoved = false;
foreach (Selector selector in _forms.Keys)
{
PdfImportedObjectTable table = _forms[selector];
if (table.ExternalDocument == null)
{
_forms.Remove(selector);
itemRemoved = true;
break;
}
}
}
}
/// <summary>
/// Map from Selector to PdfImportedObjectTable.
/// </summary>
readonly Dictionary<Selector, PdfImportedObjectTable> _forms = new Dictionary<Selector, PdfImportedObjectTable>();
/// <summary>
/// A collection of information that uniquely identifies a particular ImportedObjectTable.
/// </summary>
public class Selector
{
/// <summary>
/// Initializes a new instance of FormSelector from an XPdfForm.
/// </summary>
public Selector(XForm form)
{
// HACK: just use full path to identify
_path = form._path.ToLowerInvariant();
}
/// <summary>
/// Initializes a new instance of FormSelector from a PdfPage.
/// </summary>
public Selector(PdfPage page)
{
PdfDocument owner = page.Owner;
_path = "*" + owner.Guid.ToString("B");
_path = _path.ToLowerInvariant();
}
public Selector(PdfDocument document)
{
_path = "*" + document.Guid.ToString("B");
_path = _path.ToLowerInvariant();
}
public string Path
{
get { return _path; }
set { _path = value; }
}
string _path;
public override bool Equals(object obj)
{
Selector selector = obj as Selector;
if (selector == null)
return false;
return _path == selector._path;
}
public override int GetHashCode()
{
return _path.GetHashCode();
}
}
}
}

View File

@@ -0,0 +1,90 @@
#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
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF group XObject.
/// </summary>
public abstract class PdfGroupAttributes : PdfDictionary
{
internal PdfGroupAttributes(PdfDocument thisDocument)
: base(thisDocument)
{
Elements.SetName(Keys.Type, "/Group");
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public class Keys : KeysBase
{
/// <summary>
///(Optional) The type of PDF object that this dictionary describes;
///if present, must be Group for a group attributes dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Type = "/Type";
/// <summary>
/// (Required) The group subtype, which identifies the type of group whose
/// attributes this dictionary describes and determines the format and meaning
/// of the dictionary<72>s remaining entries. The only group subtype defined in
/// PDF 1.4 is Transparency. Other group subtypes may be added in the future.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string S = "/S";
/// <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; }
}
}
}

View File

@@ -0,0 +1,840 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
// Thomas Hövel
//
// 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.
// Some routines were translated from LibTiff.
// LibTiff copyright notice:
// Copyright (c) 1988-1997 Sam Leffler
// Copyright (c) 1991-1997 Silicon Graphics, Inc.
//
// Permission to use, copy, modify, distribute, and sell this software and
// its documentation for any purpose is hereby granted without fee, provided
// that (i) the above copyright notices and this permission notice appear in
// all copies of the software and related documentation, and (ii) the names of
// Sam Leffler and Silicon Graphics may not be used in any advertising or
// publicity relating to the software without the specific, prior written
// permission of Sam Leffler and Silicon Graphics.
//
// THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
// ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
#endregion
#define USE_GOTO
using System;
using System.Diagnostics;
namespace PdfSharp.Pdf.Advanced
{
partial class PdfImage
{
internal readonly static uint[] WhiteTerminatingCodes =
{
0x35, 8, //00110101 // 0
0x07, 6, //000111
0x07, 4, //0111
0x08, 4, //1000
0x0b, 4, //1011
0x0c, 4, //1100
0x0e, 4, //1110
0x0f, 4, //1111
0x13, 5, //10011
0x14, 5, //10100
0x07, 5, //00111 // 10
0x08, 5, //01000
0x08, 6, //001000
0x03, 6, //000011
0x34, 6, //110100
0x35, 6, //110101
0x2a, 6, //101010 // 16
0x2b, 6, //101011
0x27, 7, //0100111
0x0c, 7, //0001100
0x08, 7, //0001000 // 20
0x17, 7, //0010111
0x03, 7, //0000011
0x04, 7, //0000100
0x28, 7, //0101000
0x2b, 7, //0101011
0x13, 7, //0010011
0x24, 7, //0100100
0x18, 7, //0011000
0x02, 8, //00000010
0x03, 8, //00000011 // 30
0x1a, 8, //00011010
0x1b, 8, //00011011 // 32
0x12, 8, //00010010
0x13, 8, //00010011
0x14, 8, //00010100
0x15, 8, //00010101
0x16, 8, //00010110
0x17, 8, //00010111
0x28, 8, //00101000
0x29, 8, //00101001 // 40
0x2a, 8, //00101010
0x2b, 8, //00101011
0x2c, 8, //00101100
0x2d, 8, //00101101
0x04, 8, //00000100
0x05, 8, //00000101
0x0a, 8, //00001010
0x0b, 8, //00001011 // 48
0x52, 8, //01010010
0x53, 8, //01010011 // 50
0x54, 8, //01010100
0x55, 8, //01010101
0x24, 8, //00100100
0x25, 8, //00100101
0x58, 8, //01011000
0x59, 8, //01011001
0x5a, 8, //01011010
0x5b, 8, //01011011
0x4a, 8, //01001010
0x4b, 8, //01001011 // 60
0x32, 8, //00110010
0x33, 8, //00110011
0x34, 8, //00110100 // 63
};
internal readonly static uint[] BlackTerminatingCodes =
{
0x37, 10, //0000110111 // 0
0x02, 3, //010
0x03, 2, //11
0x02, 2, //10
0x03, 3, //011
0x03, 4, //0011
0x02, 4, //0010
0x03, 5, //00011
0x05, 6, //000101
0x04, 6, //000100
0x04, 7, //0000100
0x05, 7, //0000101
0x07, 7, //0000111
0x04, 8, //00000100
0x07, 8, //00000111
0x18, 9, //000011000
0x17, 10, //0000010111 // 16
0x18, 10, //0000011000
0x08, 10, //0000001000
0x67, 11, //00001100111
0x68, 11, //00001101000
0x6c, 11, //00001101100
0x37, 11, //00000110111
0x28, 11, //00000101000
0x17, 11, //00000010111
0x18, 11, //00000011000
0xca, 12, //000011001010
0xcb, 12, //000011001011
0xcc, 12, //000011001100
0xcd, 12, //000011001101
0x68, 12, //000001101000 // 30
0x69, 12, //000001101001
0x6a, 12, //000001101010 // 32
0x6b, 12, //000001101011
0xd2, 12, //000011010010
0xd3, 12, //000011010011
0xd4, 12, //000011010100
0xd5, 12, //000011010101
0xd6, 12, //000011010110
0xd7, 12, //000011010111
0x6c, 12, //000001101100
0x6d, 12, //000001101101
0xda, 12, //000011011010
0xdb, 12, //000011011011
0x54, 12, //000001010100
0x55, 12, //000001010101
0x56, 12, //000001010110
0x57, 12, //000001010111
0x64, 12, //000001100100 // 48
0x65, 12, //000001100101
0x52, 12, //000001010010
0x53, 12, //000001010011
0x24, 12, //000000100100
0x37, 12, //000000110111
0x38, 12, //000000111000
0x27, 12, //000000100111
0x28, 12, //000000101000
0x58, 12, //000001011000
0x59, 12, //000001011001
0x2b, 12, //000000101011
0x2c, 12, //000000101100
0x5a, 12, //000001011010
0x66, 12, //000001100110
0x67, 12, //000001100111 // 63
};
internal readonly static uint[] WhiteMakeUpCodes =
{
0x1b, 5, //11011 64 // 0
0x12, 5, //10010 128
0x17, 6, //010111 192
0x37, 7, //0110111 256
0x36, 8, //00110110 320
0x37, 8, //00110111 384
0x64, 8, //01100100 448
0x65, 8, //01100101 512
0x68, 8, //01101000 576
0x67, 8, //01100111 640
0xcc, 9, //011001100 704 // 10
0xcd, 9, //011001101 768
0xd2, 9, //011010010 832
0xd3, 9, //011010011 896
0xd4, 9, //011010100 960
0xd5, 9, //011010101 1024
0xd6, 9, //011010110 1088 // 16
0xd7, 9, //011010111 1152
0xd8, 9, //011011000 1216
0xd9, 9, //011011001 1280
0xda, 9, //011011010 1344
0xdb, 9, //011011011 1408
0x98, 9, //010011000 1472
0x99, 9, //010011001 1536
0x9a, 9, //010011010 1600
0x18, 6, //011000 1664
0x9b, 9, //010011011 1728
// Common codes for white and black:
0x08, 11, //00000001000 1792
0x0c, 11, //00000001100 1856
0x0d, 11, //00000001101 1920
0x12, 12, //000000010010 1984
0x13, 12, //000000010011 2048
0x14, 12, //000000010100 2112 // 32
0x15, 12, //000000010101 2176
0x16, 12, //000000010110 2240
0x17, 12, //000000010111 2304
0x1c, 12, //000000011100 2368
0x1d, 12, //000000011101 2432
0x1e, 12, //000000011110 2496
0x1f, 12, //000000011111 2560
0x01, 12, //000000000001 EOL // 40
};
internal readonly static uint[] BlackMakeUpCodes =
{
0x0f, 10, //0000001111 64 // 0
0xc8, 12, //000011001000 128
0xc9, 12, //000011001001 192
0x5b, 12, //000001011011 256
0x33, 12, //000000110011 320
0x34, 12, //000000110100 384
0x35, 12, //000000110101 448
0x6c, 13, //0000001101100 512
0x6d, 13, //0000001101101 576
0x4a, 13, //0000001001010 640
0x4b, 13, //0000001001011 704
0x4c, 13, //0000001001100 768
0x4d, 13, //0000001001101 832
0x72, 13, //0000001110010 896
0x73, 13, //0000001110011 960
0x74, 13, //0000001110100 1024
0x75, 13, //0000001110101 1088 // 16
0x76, 13, //0000001110110 1152
0x77, 13, //0000001110111 1216
0x52, 13, //0000001010010 1280
0x53, 13, //0000001010011 1344
0x54, 13, //0000001010100 1408
0x55, 13, //0000001010101 1472
0x5a, 13, //0000001011010 1536
0x5b, 13, //0000001011011 1600
0x64, 13, //0000001100100 1664
0x65, 13, //0000001100101 1728
// Common codes for white and black:
0x08, 11, //00000001000 1792
0x0c, 11, //00000001100 1856
0x0d, 11, //00000001101 1920
0x12, 12, //000000010010 1984
0x13, 12, //000000010011 2048
0x14, 12, //000000010100 2112 // 32
0x15, 12, //000000010101 2176
0x16, 12, //000000010110 2240
0x17, 12, //000000010111 2304
0x1c, 12, //000000011100 2368
0x1d, 12, //000000011101 2432
0x1e, 12, //000000011110 2496
0x1f, 12, //000000011111 2560
0x01, 12, //000000000001 EOL // 40
};
internal readonly static uint[] HorizontalCodes = { 0x1, 3 }; /* 001 */
internal readonly static uint[] PassCodes = { 0x1, 4, }; /* 0001 */
internal readonly static uint[] VerticalCodes =
{
0x03, 7, /* 0000 011 */
0x03, 6, /* 0000 11 */
0x03, 3, /* 011 */
0x1, 1, /* 1 */
0x2, 3, /* 010 */
0x02, 6, /* 0000 10 */
0x02, 7, /* 0000 010 */
};
readonly static uint[] _zeroRuns =
{
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
};
readonly static uint[] _oneRuns =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
};
/// <summary>
/// Counts the consecutive one bits in an image line.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="bitsLeft">The bits left.</param>
private static uint CountOneBits(BitReader reader, uint bitsLeft)
{
uint found = 0;
for (;;)
{
uint bits;
int @byte = reader.PeekByte(out bits);
uint hits = _oneRuns[@byte];
if (hits < bits)
{
if (hits > 0)
reader.SkipBits(hits);
found += hits;
return found >= bitsLeft ? bitsLeft : found;
}
found += bits;
if (found >= bitsLeft)
return bitsLeft;
reader.NextByte();
}
}
/// <summary>
/// Counts the consecutive zero bits in an image line.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="bitsLeft">The bits left.</param>
private static uint CountZeroBits(BitReader reader, uint bitsLeft)
{
uint found = 0;
for (;;)
{
uint bits;
int @byte = reader.PeekByte(out bits);
uint hits = _zeroRuns[@byte];
if (hits < bits)
{
if (hits > 0)
reader.SkipBits(hits);
found += hits;
return found >= bitsLeft ? bitsLeft : found;
}
found += bits;
if (found >= bitsLeft)
return bitsLeft;
reader.NextByte();
}
}
/// <summary>
/// Returns the offset of the next bit in the range
/// [bitStart..bitEnd] that is different from the
/// specified color. The end, bitEnd, is returned
/// if no such bit exists.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="bitStart">The offset of the start bit.</param>
/// <param name="bitEnd">The offset of the end bit.</param>
/// <param name="searchOne">If set to <c>true</c> searches "one" (i. e. white), otherwise searches black.</param>
/// <returns>The offset of the first non-matching bit.</returns>
private static uint FindDifference(BitReader reader, uint bitStart, uint bitEnd, bool searchOne)
{
// Translated from LibTiff
reader.SetPosition(bitStart);
return (bitStart + (searchOne ? CountOneBits(reader, bitEnd - bitStart) : CountZeroBits(reader, bitEnd - bitStart)));
}
/// <summary>
/// Returns the offset of the next bit in the range
/// [bitStart..bitEnd] that is different from the
/// specified color. The end, bitEnd, is returned
/// if no such bit exists.
/// Like FindDifference, but also check the
/// starting bit against the end in case start > end.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="bitStart">The offset of the start bit.</param>
/// <param name="bitEnd">The offset of the end bit.</param>
/// <param name="searchOne">If set to <c>true</c> searches "one" (i. e. white), otherwise searches black.</param>
/// <returns>The offset of the first non-matching bit.</returns>
private static uint FindDifferenceWithCheck(BitReader reader, uint bitStart, uint bitEnd, bool searchOne)
{
// Translated from LibTiff
return ((bitStart < bitEnd) ? FindDifference(reader, bitStart, bitEnd, searchOne) : bitEnd);
}
/// <summary>
/// 2d-encode a row of pixels. Consult the CCITT documentation for the algorithm.
/// </summary>
/// <param name="writer">The writer.</param>
/// <param name="bytesFileOffset">Offset of image data in bitmap file.</param>
/// <param name="imageBits">The bitmap file.</param>
/// <param name="currentRow">Index of the current row.</param>
/// <param name="referenceRow">Index of the reference row (0xffffffff if there is none).</param>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="bytesPerLineBmp">The bytes per line in the bitmap file.</param>
static void FaxEncode2DRow(BitWriter writer, uint bytesFileOffset, byte[] imageBits, uint currentRow, uint referenceRow, uint width, uint height, uint bytesPerLineBmp)
{
// Translated from LibTiff
uint bytesOffsetRead = bytesFileOffset + (height - 1 - currentRow) * bytesPerLineBmp;
BitReader reader = new BitReader(imageBits, bytesOffsetRead, width);
BitReader readerReference;
if (referenceRow != 0xffffffff)
{
uint bytesOffsetReadReference = bytesFileOffset + (height - 1 - referenceRow) * bytesPerLineBmp;
readerReference = new BitReader(imageBits, bytesOffsetReadReference, width);
}
else
{
byte[] tmpImageBits = new byte[bytesPerLineBmp];
for (int i = 0; i < bytesPerLineBmp; ++i)
tmpImageBits[i] = 255;
readerReference = new BitReader(tmpImageBits, 0, width);
}
uint a0 = 0;
uint a1 = !reader.GetBit(0) ? 0 : FindDifference(reader, 0, width, true);
uint b1 = !readerReference.GetBit(0) ? 0 : FindDifference(readerReference, 0, width, true);
// ReSharper disable TooWideLocalVariableScope
uint a2, b2;
// ReSharper restore TooWideLocalVariableScope
for (;;)
{
b2 = FindDifferenceWithCheck(readerReference, b1, width, readerReference.GetBit(b1));
if (b2 >= a1)
{
int d = (int)b1 - (int)a1;
if (!(-3 <= d && d <= 3))
{
/* horizontal mode */
a2 = FindDifferenceWithCheck(reader, a1, width, reader.GetBit(a1));
writer.WriteTableLine(HorizontalCodes, 0);
if (a0 + a1 == 0 || reader.GetBit(a0))
{
WriteSample(writer, a1 - a0, true);
WriteSample(writer, a2 - a1, false);
}
else
{
WriteSample(writer, a1 - a0, false);
WriteSample(writer, a2 - a1, true);
}
a0 = a2;
}
else
{
/* vertical mode */
writer.WriteTableLine(VerticalCodes, (uint)(d + 3));
a0 = a1;
}
}
else
{
/* pass mode */
writer.WriteTableLine(PassCodes, 0);
a0 = b2;
}
if (a0 >= width)
break;
bool bitA0 = reader.GetBit(a0);
a1 = FindDifference(reader, a0, width, bitA0/*reader.GetBit(a0)*/);
b1 = FindDifference(readerReference, a0, width, !bitA0/*reader.GetBit(a0)*/);
b1 = FindDifferenceWithCheck(readerReference, b1, width, bitA0/*reader.GetBit(a0)*/);
}
}
/// <summary>
/// Encodes a bitonal bitmap using 1D CCITT fax encoding.
/// </summary>
/// <param name="imageData">Space reserved for the fax encoded bitmap. An exception will be thrown if this buffer is too small.</param>
/// <param name="imageBits">The bitmap to be encoded.</param>
/// <param name="bytesFileOffset">Offset of image data in bitmap file.</param>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <returns>The size of the fax encoded image (0 on failure).</returns>
private static int DoFaxEncoding(ref byte[] imageData, byte[] imageBits, uint bytesFileOffset, uint width, uint height)
{
try
{
uint bytesPerLineBmp = ((width + 31) / 32) * 4;
BitWriter writer = new BitWriter(ref imageData);
for (uint y = 0; y < height; ++y)
{
uint bytesOffsetRead = bytesFileOffset + (height - 1 - y) * bytesPerLineBmp;
BitReader reader = new BitReader(imageBits, bytesOffsetRead, width);
for (uint bitsRead = 0; bitsRead < width;)
{
uint white = CountOneBits(reader, width - bitsRead);
WriteSample(writer, white, true);
bitsRead += white;
if (bitsRead < width)
{
uint black = CountZeroBits(reader, width - bitsRead);
WriteSample(writer, black, false);
bitsRead += black;
}
}
}
writer.FlushBuffer();
return writer.BytesWritten();
}
catch (Exception /*ex*/)
{
//ex.GetType();
return 0;
}
}
/// <summary>
/// Encodes a bitonal bitmap using 2D group 4 CCITT fax encoding.
/// </summary>
/// <param name="imageData">Space reserved for the fax encoded bitmap. An exception will be thrown if this buffer is too small.</param>
/// <param name="imageBits">The bitmap to be encoded.</param>
/// <param name="bytesFileOffset">Offset of image data in bitmap file.</param>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <returns>The size of the fax encoded image (0 on failure).</returns>
internal static int DoFaxEncodingGroup4(ref byte[] imageData, byte[] imageBits, uint bytesFileOffset, uint width, uint height)
{
try
{
uint bytesPerLineBmp = ((width + 31) / 32) * 4;
BitWriter writer = new BitWriter(ref imageData);
for (uint y = 0; y < height; ++y)
{
FaxEncode2DRow(writer, bytesFileOffset, imageBits, y, (y != 0) ? y - 1 : 0xffffffff, width, height, bytesPerLineBmp);
}
writer.FlushBuffer();
return writer.BytesWritten();
}
catch (Exception ex)
{
ex.GetType();
return 0;
}
}
/// <summary>
/// Writes the image data.
/// </summary>
/// <param name="writer">The writer.</param>
/// <param name="count">The count of bits (pels) to encode.</param>
/// <param name="white">The color of the pels.</param>
private static void WriteSample(BitWriter writer, uint count, bool white)
{
uint[] terminatingCodes = white ? WhiteTerminatingCodes : BlackTerminatingCodes;
uint[] makeUpCodes = white ? WhiteMakeUpCodes : BlackMakeUpCodes;
// The make-up code for 2560 will be written as often as required:
while (count >= 2624)
{
writer.WriteTableLine(makeUpCodes, 39); // Magic: 2560
count -= 2560;
}
// A make-up code for a multiple of 64 will be written if required:
if (count > 63)
{
uint line = count / 64 - 1;
writer.WriteTableLine(makeUpCodes, line);
count -= (line + 1) * 64;
}
// And finally the terminating code for the remaining value (0 through 63):
writer.WriteTableLine(terminatingCodes, count);
}
}
/// <summary>
/// The BitReader class is a helper to read bits from an in-memory bitmap file.
/// </summary>
class BitReader
{
readonly byte[] _imageBits;
uint _bytesOffsetRead;
readonly uint _bytesFileOffset;
byte _buffer;
uint _bitsInBuffer;
readonly uint _bitsTotal; // Bits we may read (bits per image line)
/// <summary>
/// Initializes a new instance of the <see cref="BitReader"/> class.
/// </summary>
/// <param name="imageBits">The in-memory bitmap file.</param>
/// <param name="bytesFileOffset">The offset of the line to read.</param>
/// <param name="bits">The count of bits that may be read (i. e. the width of the image for normal usage).</param>
internal BitReader(byte[] imageBits, uint bytesFileOffset, uint bits)
{
_imageBits = imageBits;
_bytesFileOffset = bytesFileOffset;
_bitsTotal = bits;
_bytesOffsetRead = bytesFileOffset;
_buffer = imageBits[_bytesOffsetRead];
_bitsInBuffer = 8;
}
/// <summary>
/// Sets the position within the line (needed for 2D encoding).
/// </summary>
/// <param name="position">The new position.</param>
internal void SetPosition(uint position)
{
_bytesOffsetRead = _bytesFileOffset + (position >> 3);
_buffer = _imageBits[_bytesOffsetRead];
_bitsInBuffer = 8 - (position & 0x07);
}
/// <summary>
/// Gets a single bit at the specified position.
/// </summary>
/// <param name="position">The position.</param>
/// <returns>True if bit is set.</returns>
internal bool GetBit(uint position)
{
if (position >= _bitsTotal)
return false;
SetPosition(position);
uint dummy;
return (PeekByte(out dummy) & 0x80) > 0;
}
/// <summary>
/// Returns the bits that are in the buffer (without changing the position).
/// Data is MSB aligned.
/// </summary>
/// <param name="bits">The count of bits that were returned (1 through 8).</param>
/// <returns>The MSB aligned bits from the buffer.</returns>
internal byte PeekByte(out uint bits)
{
// TODO: try to make this faster!
if (_bitsInBuffer == 8)
{
bits = 8;
return _buffer;
}
bits = _bitsInBuffer;
return (byte)(_buffer << (int)(8 - _bitsInBuffer));
}
/// <summary>
/// Moves the buffer to the next byte.
/// </summary>
internal void NextByte()
{
_buffer = _imageBits[++_bytesOffsetRead];
_bitsInBuffer = 8;
}
/// <summary>
/// "Removes" (eats) bits from the buffer.
/// </summary>
/// <param name="bits">The count of bits that were processed.</param>
internal void SkipBits(uint bits)
{
Debug.Assert(bits <= _bitsInBuffer, "Buffer underrun");
if (bits == _bitsInBuffer)
{
NextByte();
return;
}
_bitsInBuffer -= bits;
}
}
/// <summary>
/// A helper class for writing groups of bits into an array of bytes.
/// </summary>
class BitWriter
{
/// <summary>
/// Initializes a new instance of the <see cref="BitWriter"/> class.
/// </summary>
/// <param name="imageData">The byte array to be written to.</param>
internal BitWriter(ref byte[] imageData)
{
_imageData = imageData;
}
/// <summary>
/// Writes the buffered bits into the byte array.
/// </summary>
internal void FlushBuffer()
{
if (_bitsInBuffer > 0)
{
uint bits = 8 - _bitsInBuffer;
WriteBits(0, bits);
}
}
/// <summary>
/// Masks for n bits in a byte (with n = 0 through 8).
/// </summary>
static readonly uint[] masks = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
/// <summary>
/// Writes bits to the byte array.
/// </summary>
/// <param name="value">The bits to be written (LSB aligned).</param>
/// <param name="bits">The count of bits.</param>
internal void WriteBits(uint value, uint bits)
{
#if true
// TODO: Try to make this faster!
// If we have to write more bits than fit into the buffer, we fill
// the buffer and call the same routine recursively for the rest.
#if USE_GOTO
// Use GOTO instead of end recursion: (is this faster?)
SimulateRecursion:
#endif
if (bits + _bitsInBuffer > 8)
{
// We can't add all bits this time.
uint bitsNow = 8 - _bitsInBuffer;
uint bitsRemainder = bits - bitsNow;
WriteBits(value >> (int)(bitsRemainder), bitsNow); // that fits
#if USE_GOTO
bits = bitsRemainder;
goto SimulateRecursion;
#else
WriteBits(value, bitsRemainder);
return;
#endif
}
_buffer = (_buffer << (int)bits) + (value & masks[bits]);
_bitsInBuffer += bits;
if (_bitsInBuffer == 8)
{
// The line below will sometimes throw a System.IndexOutOfRangeException while PDFsharp tries different formats for monochrome bitmaps (exception occurs if CCITT encoding requires more space than an uncompressed bitmap).
_imageData[_bytesOffsetWrite] = (byte)_buffer;
_bitsInBuffer = 0;
++_bytesOffsetWrite;
}
#else
// Simple implementation writing bit by bit:
int mask = 1 << (int)(bits - 1);
for (int b = 0; b < bits; ++b)
{
if ((value & mask) != 0)
buffer = (buffer << 1) + 1;
else
buffer = buffer << 1;
++bitsInBuffer;
mask /= 2;
if (bitsInBuffer == 8)
{
imageData[bytesOffsetWrite] = (byte)buffer;
bitsInBuffer = 0;
++bytesOffsetWrite;
}
}
#endif
}
/// <summary>
/// Writes a line from a look-up table.
/// A "line" in the table are two integers, one containing the values, one containing the bit count.
/// </summary>
internal void WriteTableLine(uint[] table, uint line)
{
uint value = table[line * 2];
uint bits = table[line * 2 + 1];
WriteBits(value, bits);
}
[Obsolete]
internal void WriteEOL()
{
// Not needed for PDF.
WriteTableLine(PdfImage.WhiteMakeUpCodes, 40);
}
/// <summary>
/// Flushes the buffer and returns the count of bytes written to the array.
/// </summary>
internal int BytesWritten()
{
FlushBuffer();
return _bytesOffsetWrite;
}
int _bytesOffsetWrite;
readonly byte[] _imageData;
uint _buffer;
uint _bitsInBuffer;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
#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.Collections.Generic;
using System.Globalization;
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Contains all used images of a document.
/// </summary>
internal sealed class PdfImageTable : PdfResourceTable
{
/// <summary>
/// Initializes a new instance of this class, which is a singleton for each document.
/// </summary>
public PdfImageTable(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Gets a PdfImage from an XImage. If no PdfImage already exists, a new one is created.
/// </summary>
public PdfImage GetImage(XImage image)
{
ImageSelector selector = image._selector;
if (selector == null)
{
selector = new ImageSelector(image);
image._selector = selector;
}
PdfImage pdfImage;
if (!_images.TryGetValue(selector, out pdfImage))
{
pdfImage = new PdfImage(Owner, image);
//pdfImage.Document = _document;
Debug.Assert(pdfImage.Owner == Owner);
_images[selector] = pdfImage;
}
return pdfImage;
}
/// <summary>
/// Map from ImageSelector to PdfImage.
/// </summary>
readonly Dictionary<ImageSelector, PdfImage> _images = new Dictionary<ImageSelector, PdfImage>();
/// <summary>
/// A collection of information that uniquely identifies a particular PdfImage.
/// </summary>
public class ImageSelector
{
/// <summary>
/// Initializes a new instance of ImageSelector from an XImage.
/// </summary>
public ImageSelector(XImage image)
{
// HACK: implement a way to identify images when they are reused
// TODO 4STLA Implementation that calculates MD5 hashes for images generated for the images can be found here: http://forum.pdfsharp.net/viewtopic.php?p=6959#p6959
if (image._path == null)
image._path = "*" + Guid.NewGuid().ToString("B");
// HACK: just use full path to identify
_path = image._path.ToLowerInvariant();
}
public string Path
{
get { return _path; }
set { _path = value; }
}
string _path;
public override bool Equals(object obj)
{
ImageSelector selector = obj as ImageSelector;
if (selector == null)
return false;
return _path == selector._path;
}
public override int GetHashCode()
{
return _path.GetHashCode();
}
}
}
}

View File

@@ -0,0 +1,117 @@
#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.Collections.Generic;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents the imported objects of an external document. Used to cache objects that are
/// already imported when a PdfFormXObject is added to a page.
/// </summary>
internal sealed class PdfImportedObjectTable
{
/// <summary>
/// Initializes a new instance of this class with the document the objects are imported from.
/// </summary>
public PdfImportedObjectTable(PdfDocument owner, PdfDocument externalDocument)
{
if (owner == null)
throw new ArgumentNullException("owner");
if (externalDocument == null)
throw new ArgumentNullException("externalDocument");
_owner = owner;
_externalDocumentHandle = externalDocument.Handle;
_xObjects = new PdfFormXObject[externalDocument.PageCount];
}
readonly PdfFormXObject[] _xObjects;
/// <summary>
/// Gets the document this table belongs to.
/// </summary>
public PdfDocument Owner
{
get { return _owner; }
}
readonly PdfDocument _owner;
/// <summary>
/// Gets the external document, or null, if the external document is garbage collected.
/// </summary>
public PdfDocument ExternalDocument
{
get { return _externalDocumentHandle.IsAlive ? _externalDocumentHandle.Target : null; }
}
readonly PdfDocument.DocumentHandle _externalDocumentHandle;
public PdfFormXObject GetXObject(int pageNumber)
{
return _xObjects[pageNumber - 1];
}
public void SetXObject(int pageNumber, PdfFormXObject xObject)
{
_xObjects[pageNumber - 1] = xObject;
}
/// <summary>
/// Indicates whether the specified object is already imported.
/// </summary>
public bool Contains(PdfObjectID externalID)
{
return _externalIDs.ContainsKey(externalID.ToString());
}
/// <summary>
/// Adds a cloned object to this table.
/// </summary>
/// <param name="externalID">The object identifier in the foreign object.</param>
/// <param name="iref">The cross reference to the clone of the foreign object, which belongs to
/// this document. In general the clone has a different object identifier.</param>
public void Add(PdfObjectID externalID, PdfReference iref)
{
_externalIDs[externalID.ToString()] = iref;
}
/// <summary>
/// Gets the cloned object that corresponds to the specified external identifier.
/// </summary>
public PdfReference this[PdfObjectID externalID]
{
get { return _externalIDs[externalID.ToString()]; }
}
/// <summary>
/// Maps external object identifiers to cross reference entries of the importing document
/// {PdfObjectID -> PdfReference}.
/// </summary>
readonly Dictionary<string, PdfReference> _externalIDs = new Dictionary<string, PdfReference>();
}
}

View File

@@ -0,0 +1,298 @@
#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.Reflection;
using System.Text;
using System.IO;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Provides access to the internal document data structures. This class prevents the public
/// interfaces from pollution with to much internal functions.
/// </summary>
public class PdfInternals // TODO: PdfDocumentInternals... PdfPageInterals etc.
{
internal PdfInternals(PdfDocument document)
{
_document = document;
}
readonly PdfDocument _document;
/// <summary>
/// Gets or sets the first document identifier.
/// </summary>
public string FirstDocumentID
{
get { return _document._trailer.GetDocumentID(0); }
set { _document._trailer.SetDocumentID(0, value); }
}
/// <summary>
/// Gets the first document identifier as GUID.
/// </summary>
public Guid FirstDocumentGuid
{
get { return GuidFromString(_document._trailer.GetDocumentID(0)); }
}
/// <summary>
/// Gets or sets the second document identifier.
/// </summary>
public string SecondDocumentID
{
get { return _document._trailer.GetDocumentID(1); }
set { _document._trailer.SetDocumentID(1, value); }
}
/// <summary>
/// Gets the first document identifier as GUID.
/// </summary>
public Guid SecondDocumentGuid
{
get { return GuidFromString(_document._trailer.GetDocumentID(0)); }
}
Guid GuidFromString(string id)
{
if (id == null || id.Length != 16)
return Guid.Empty;
StringBuilder guid = new StringBuilder();
for (int idx = 0; idx < 16; idx++)
guid.AppendFormat("{0:X2}", (byte)id[idx]);
return new Guid(guid.ToString());
}
/// <summary>
/// Gets the catalog dictionary.
/// </summary>
public PdfCatalog Catalog
{
get { return _document.Catalog; }
}
/// <summary>
/// Gets the ExtGStateTable object.
/// </summary>
public PdfExtGStateTable ExtGStateTable
{
get { return _document.ExtGStateTable; }
}
/// <summary>
/// Returns the object with the specified Identifier, or null, if no such object exists.
/// </summary>
public PdfObject GetObject(PdfObjectID objectID)
{
return _document._irefTable[objectID].Value;
}
/// <summary>
/// Maps the specified external object to the substitute object in this document.
/// Returns null if no such object exists.
/// </summary>
public PdfObject MapExternalObject(PdfObject externalObject)
{
PdfFormXObjectTable table = _document.FormTable;
PdfImportedObjectTable iot = table.GetImportedObjectTable(externalObject.Owner);
PdfReference reference = iot[externalObject.ObjectID];
return reference == null ? null : reference.Value;
}
/// <summary>
/// Returns the PdfReference of the specified object, or null, if the object is not in the
/// document's object table.
/// </summary>
public static PdfReference GetReference(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
return obj.Reference;
}
/// <summary>
/// Gets the object identifier of the specified object.
/// </summary>
public static PdfObjectID GetObjectID(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
return obj.ObjectID;
}
/// <summary>
/// Gets the object number of the specified object.
/// </summary>
public static int GetObjectNumber(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
return obj.ObjectNumber;
}
/// <summary>
/// Gets the generation number of the specified object.
/// </summary>
public static int GenerationNumber(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
return obj.GenerationNumber;
}
/// <summary>
/// Gets all indirect objects ordered by their object identifier.
/// </summary>
public PdfObject[] GetAllObjects()
{
PdfReference[] irefs = _document._irefTable.AllReferences;
int count = irefs.Length;
PdfObject[] objects = new PdfObject[count];
for (int idx = 0; idx < count; idx++)
objects[idx] = irefs[idx].Value;
return objects;
}
/// <summary>
/// Gets all indirect objects ordered by their object identifier.
/// </summary>
[Obsolete("Use GetAllObjects.")] // Properties should not return arrays
public PdfObject[] AllObjects
{
get { return GetAllObjects(); }
}
/// <summary>
/// Creates the indirect object of the specified type, adds it to the document,
/// and returns the object.
/// </summary>
public T CreateIndirectObject<T>() where T : PdfObject
{
#if true
T obj = Activator.CreateInstance<T>();
_document._irefTable.Add(obj);
#else
T result = null;
#if !NETFX_CORE && !UWP
ConstructorInfo ctorInfo = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.ExactBinding,
null, new Type[] { typeof(PdfDocument) }, null);
#else
ConstructorInfo ctorInfo = null; // TODO
#endif
if (ctorInfo != null)
{
result = (T)ctorInfo.Invoke(new object[] { _document });
Debug.Assert(result != null);
AddObject(result);
}
Debug.Assert(result != null, "CreateIndirectObject failed with type " + typeof(T).FullName);
#endif
return obj;
}
/// <summary>
/// Adds an object to the PDF document. This operation and only this operation makes the object
/// an indirect object owned by this document.
/// </summary>
public void AddObject(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
if (obj.Owner == null)
obj.Document = _document;
else if (obj.Owner != _document)
throw new InvalidOperationException("Object does not belong to this document.");
_document._irefTable.Add(obj);
}
/// <summary>
/// Removes an object from the PDF document.
/// </summary>
public void RemoveObject(PdfObject obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
if (obj.Reference == null)
throw new InvalidOperationException("Only indirect objects can be removed.");
if (obj.Owner != _document)
throw new InvalidOperationException("Object does not belong to this document.");
_document._irefTable.Remove(obj.Reference);
}
/// <summary>
/// Returns an array containing the specified object as first element follows by its transitive
/// closure. The closure of an object are all objects that can be reached by indirect references.
/// The transitive closure is the result of applying the calculation of the closure to a closure
/// as long as no new objects came along. This is e.g. useful for getting all objects belonging
/// to the resources of a page.
/// </summary>
public PdfObject[] GetClosure(PdfObject obj)
{
return GetClosure(obj, Int32.MaxValue);
}
/// <summary>
/// Returns an array containing the specified object as first element follows by its transitive
/// closure limited by the specified number of iterations.
/// </summary>
public PdfObject[] GetClosure(PdfObject obj, int depth)
{
PdfReference[] references = _document._irefTable.TransitiveClosure(obj, depth);
int count = references.Length + 1;
PdfObject[] objects = new PdfObject[count];
objects[0] = obj;
for (int idx = 1; idx < count; idx++)
objects[idx] = references[idx - 1].Value;
return objects;
}
/// <summary>
/// Writes a PdfItem into the specified stream.
/// </summary>
// This function exists to keep PdfWriter and PdfItem.WriteObject internal.
public void WriteObject(Stream stream, PdfItem item)
{
// Never write an encrypted object
PdfWriter writer = new PdfWriter(stream, null);
writer.Options = PdfWriterOptions.OmitStream;
item.WriteObject(writer);
}
/// <summary>
/// The name of the custom value key.
/// </summary>
public string CustomValueKey = "/PdfSharp.CustomValue";
}
}

View File

@@ -0,0 +1,84 @@
#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
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Provides access to the internal PDF object data structures. This class prevents the public
/// interfaces from pollution with to much internal functions.
/// </summary>
public class PdfObjectInternals
{
internal PdfObjectInternals(PdfObject obj)
{
_obj = obj;
}
readonly PdfObject _obj;
/// <summary>
/// Gets the object identifier. Returns PdfObjectID.Empty for direct objects.
/// </summary>
public PdfObjectID ObjectID
{
get { return _obj.ObjectID; }
}
/// <summary>
/// Gets the object number.
/// </summary>
public int ObjectNumber
{
get { return _obj.ObjectID.ObjectNumber; }
}
/// <summary>
/// Gets the generation number.
/// </summary>
public int GenerationNumber
{
get { return _obj.ObjectID.GenerationNumber; }
}
/// <summary>
/// Gets the name of the current type.
/// Not a very useful property, but can be used for data binding.
/// </summary>
public string TypeID
{
get
{
if (_obj is PdfArray)
return "array";
if (_obj is PdfDictionary)
return "dictionary";
return _obj.GetType().Name;
}
}
}
}

View File

@@ -0,0 +1,173 @@
#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.IO;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents an object stream that contains compressed objects.
/// PDF 1.5.
/// </summary>
public class PdfObjectStream : PdfDictionary
{
// Reference: 3.4.6 Object Streams / Page 100
/// <summary>
/// Initializes a new instance of the <see cref="PdfObjectStream"/> class.
/// </summary>
public PdfObjectStream(PdfDocument document)
: base(document)
{
#if DEBUG && CORE
if (Internal.PdfDiagnostics.TraceObjectStreams)
{
Debug.WriteLine("PdfObjectStream(document) created.");
}
#endif
}
/// <summary>
/// Initializes a new instance from an existing dictionary. Used for object type transformation.
/// </summary>
internal PdfObjectStream(PdfDictionary dict)
: base(dict)
{
int n = Elements.GetInteger(Keys.N);
int first = Elements.GetInteger(Keys.First);
Stream.TryUnfilter();
Parser parser = new Parser(null, new MemoryStream(Stream.Value));
_header = parser.ReadObjectStreamHeader(n, first);
#if DEBUG && CORE
if (Internal.PdfDiagnostics.TraceObjectStreams)
{
Debug.WriteLine(String.Format("PdfObjectStream(document) created. Header item count: {0}", _header.GetLength(0)));
}
#endif
}
/// <summary>
/// Reads the compressed object with the specified index.
/// </summary>
internal void ReadReferences(PdfCrossReferenceTable xrefTable)
{
////// Create parser for stream.
////Parser parser = new Parser(_document, new MemoryStream(Stream.Value));
for (int idx = 0; idx < _header.Length; idx++)
{
int objectNumber = _header[idx][0];
int offset = _header[idx][1];
PdfObjectID objectID = new PdfObjectID(objectNumber);
// HACK: -1 indicates compressed object.
PdfReference iref = new PdfReference(objectID, -1);
////iref.ObjectID = objectID;
////iref.Value = xrefStream;
if (!xrefTable.Contains(iref.ObjectID))
{
xrefTable.Add(iref);
}
else
{
GetType();
}
}
}
/// <summary>
/// Reads the compressed object with the specified index.
/// </summary>
internal PdfReference ReadCompressedObject(int index)
{
Parser parser = new Parser(_document, new MemoryStream(Stream.Value));
int objectNumber = _header[index][0];
int offset = _header[index][1];
return parser.ReadCompressedObject(objectNumber, offset);
}
/// <summary>
/// N pairs of integers.
/// The first integer represents the object number of the compressed object.
/// The second integer represents the absolute offset of that object in the decoded stream,
/// i.e. the byte offset plus First entry.
/// </summary>
private readonly int[][] _header; // Reference: Page 102
/// <summary>
/// Predefined keys common to all font dictionaries.
/// </summary>
public class Keys : PdfStream.Keys
{
// Reference: TABLE 3.14 Additional entries specific to an object stream dictionary / Page 101
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be ObjStmfor an object stream.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "ObjStm")]
public const string Type = "/Type";
/// <summary>
/// (Required) The number of compressed objects in the stream.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string N = "/N";
/// <summary>
/// (Required) The byte offset (in the decoded stream) of the first
/// compressed object.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string First = "/First";
/// <summary>
/// (Optional) A reference to an object stream, of which the current object
/// stream is considered an extension. Both streams are considered part of
/// a collection of object streams (see below). A given collection consists
/// of a set of streams whose Extendslinks form a directed acyclic graph.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string Extends = "/Extends";
}
}
#if DEBUG && CORE
static class ObjectStreamDiagnostics
{
public static void AddObjectStreamXRef()
{ }
}
#endif
}

View File

@@ -0,0 +1,73 @@
#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;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF page object.
/// </summary>
internal class PdfPageInheritableObjects : PdfDictionary
{
public PdfPageInheritableObjects()
{ }
// TODO Inheritable Resources not yet supported
/// <summary>
///
/// </summary>
public PdfRectangle MediaBox
{
get { return _mediaBox; }
set { _mediaBox = value; }
}
PdfRectangle _mediaBox;
public PdfRectangle CropBox
{
get { return _cropBox; }
set { _cropBox = value; }
}
PdfRectangle _cropBox;
public int Rotate
{
get { return _rotate; }
set
{
if (value % 90 != 0)
throw new ArgumentException("The value must be a multiple of 90.", nameof(value));
_rotate = value;
}
}
int _rotate;
}
}

View File

@@ -0,0 +1,41 @@
#region PDFsharp - A .NET library for processing PDF
//
// Authors:
// Stefan Lange
//
// Copyright (c) 2005-2017 empira Software GmbH, Cologne (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
namespace PdfSharp.Pdf.Advanced
{
#if true_ // Not yet used.
/// <summary>
/// TODO
/// </summary>
public static class PdfPageInterals
{
// TODO
}
#endif
}

View File

@@ -0,0 +1,243 @@
#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
// With this define each iref object gets a unique number (uid) to make them distinguishable in the debugger
#define UNIQUE_IREF_
using System;
using System.Collections.Generic;
using System.Diagnostics;
using PdfSharp.Pdf.IO;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents an indirect reference to a PdfObject.
/// </summary>
[DebuggerDisplay("iref({ObjectNumber}, {GenerationNumber})")]
public sealed class PdfReference : PdfItem
{
// About PdfReference
//
// * A PdfReference holds either the ObjectID or the PdfObject or both.
//
// * Each PdfObject has a PdfReference if and only if it is an indirect object. Direct objects have
// no PdfReference, because they are embedded in a parent objects.
//
// * PdfReference objects are used to reference PdfObject instances. A value in a PDF dictionary
// or array that is a PdfReference represents an indirect reference. A value in a PDF dictionary or
// or array that is a PdfObject represents a direct (or embeddded) object.
//
// * When a PDF file is imported, the PdfXRefTable is filled with PdfReference objects keeping the
// ObjectsIDs and file positions (offsets) of all indirect objects.
//
// * Indirect objects can easily be renumbered because they do not rely on their ObjectsIDs.
//
// * During modification of a document the ObjectID of an indirect object has no meaning,
// except that they must be different in pairs.
/// <summary>
/// Initializes a new PdfReference instance for the specified indirect object.
/// </summary>
public PdfReference(PdfObject pdfObject)
{
if (pdfObject.Reference != null)
throw new InvalidOperationException("Must not create iref for an object that already has one.");
_value = pdfObject;
pdfObject.Reference = this;
#if UNIQUE_IREF && DEBUG
_uid = ++s_counter;
#endif
}
/// <summary>
/// Initializes a new PdfReference instance from the specified object identifier and file position.
/// </summary>
public PdfReference(PdfObjectID objectID, int position)
{
_objectID = objectID;
_position = position;
#if UNIQUE_IREF && DEBUG
_uid = ++s_counter;
#endif
}
/// <summary>
/// Writes the object in PDF iref table format.
/// </summary>
internal void WriteXRefEnty(PdfWriter writer)
{
// PDFsharp does not yet support PDF 1.5 object streams.
// Each line must be exactly 20 bytes long, otherwise Acrobat repairs the file.
string text = String.Format("{0:0000000000} {1:00000} n\n",
_position, _objectID.GenerationNumber); // InUse ? 'n' : 'f');
writer.WriteRaw(text);
}
/// <summary>
/// Writes an indirect reference.
/// </summary>
internal override void WriteObject(PdfWriter writer)
{
writer.Write(this);
}
/// <summary>
/// Gets or sets the object identifier.
/// </summary>
public PdfObjectID ObjectID
{
get { return _objectID; }
set
{
// Ignore redundant invokations.
if (_objectID == value)
return;
_objectID = value;
if (Document != null)
{
//PdfXRefTable table = Document.xrefTable;
//table.Remove(this);
//objectID = value;
//table.Add(this);
}
}
}
PdfObjectID _objectID;
/// <summary>
/// Gets the object number of the object identifier.
/// </summary>
public int ObjectNumber
{
get { return _objectID.ObjectNumber; }
}
/// <summary>
/// Gets the generation number of the object identifier.
/// </summary>
public int GenerationNumber
{
get { return _objectID.GenerationNumber; }
}
/// <summary>
/// Gets or sets the file position of the related PdfObject.
/// </summary>
public int Position
{
get { return _position; }
set { _position = value; }
}
int _position; // I know it should be long, but I have never seen a 2GB PDF file.
//public bool InUse
//{
// get {return inUse;}
// set {inUse = value;}
//}
//bool inUse;
/// <summary>
/// Gets or sets the referenced PdfObject.
/// </summary>
public PdfObject Value
{
get { return _value; }
set
{
Debug.Assert(value != null, "The value of a PdfReference must never be null.");
Debug.Assert(value.Reference == null || ReferenceEquals(value.Reference, this), "The reference of the value must be null or this.");
_value = value;
// value must never be null
value.Reference = this;
}
}
PdfObject _value;
/// <summary>
/// Hack for dead objects.
/// </summary>
internal void SetObject(PdfObject value)
{
_value = value;
}
/// <summary>
/// Gets or sets the document this object belongs to.
/// </summary>
public PdfDocument Document
{
get { return _document; }
set { _document = value; }
}
PdfDocument _document;
/// <summary>
/// Gets a string representing the object identifier.
/// </summary>
public override string ToString()
{
return _objectID + " R";
}
internal static PdfReferenceComparer Comparer
{
get { return new PdfReferenceComparer(); }
}
/// <summary>
/// Implements a comparer that compares PdfReference objects by their PdfObjectID.
/// </summary>
internal class PdfReferenceComparer : IComparer<PdfReference>
{
public int Compare(PdfReference x, PdfReference y)
{
PdfReference l = x;
PdfReference r = y;
if (l != null)
{
if (r != null)
return l._objectID.CompareTo(r._objectID);
return -1;
}
if (r != null)
return 1;
return 0;
}
}
#if UNIQUE_IREF && DEBUG
static int s_counter = 0;
int _uid;
#endif
}
}

View File

@@ -0,0 +1,72 @@
#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.Collections.Generic;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Base class for all dictionaries that map resource names to objects.
/// </summary>
internal class PdfResourceMap : PdfDictionary //, IEnumerable
{
public PdfResourceMap()
{ }
public PdfResourceMap(PdfDocument document)
: base(document)
{ }
protected PdfResourceMap(PdfDictionary dict)
: base(dict)
{ }
// public int Count
// {
// get {return resources.Count;}
// }
//
// public PdfObject this[string key]
// {
// get {return resources[key] as PdfObject;}
// set {resources[key] = value;}
// }
/// <summary>
/// Adds all imported resource names to the specified hashtable.
/// </summary>
internal void CollectResourceNames(Dictionary<string, object> usedResourceNames)
{
// ?TODO: Imported resources (e.g. fonts) can be reused, but I think this is rather difficult. Will be an issue in PDFsharp 2.0.
PdfName[] names = Elements.KeyNames;
foreach (PdfName name in names)
usedResourceNames.Add(name.ToString(), null);
}
}
}

View File

@@ -0,0 +1,58 @@
#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;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Base class for FontTable, ImageTable, FormXObjectTable etc.
/// </summary>
public class PdfResourceTable
{
/// <summary>
/// Base class for document wide resource tables.
/// </summary>
public PdfResourceTable(PdfDocument owner)
{
if (owner == null)
throw new ArgumentNullException("owner");
_owner = owner;
}
/// <summary>
/// Gets the owning document of this resource table.
/// </summary>
protected PdfDocument Owner
{
get { return _owner; }
}
readonly PdfDocument _owner;
}
}

View File

@@ -0,0 +1,452 @@
#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.Collections.Generic;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF resource object.
/// </summary>
public sealed class PdfResources : PdfDictionary
{
// Resource management works roughly like this:
// When the user creates an XFont and uses it in the XGraphics of a PdfPage, then at the first time
// a PdfFont is created and cached in the document global font table. If the user creates a new
// XFont object for an exisisting PdfFont, the PdfFont object is reused. When the PdfFont is added
// to the resources of a PdfPage for the first time, it is added to the page local PdfResourceMap for
// fonts and automatically associated with a local resource name.
/// <summary>
/// Initializes a new instance of the <see cref="PdfResources"/> class.
/// </summary>
/// <param name="document">The document.</param>
public PdfResources(PdfDocument document)
: base(document)
{
Elements[Keys.ProcSet] = new PdfLiteral("[/PDF/Text/ImageB/ImageC/ImageI]");
}
internal PdfResources(PdfDictionary dict)
: base(dict)
{ }
/// <summary>
/// Adds the specified font to this resource dictionary and returns its local resource name.
/// </summary>
public string AddFont(PdfFont font)
{
string name;
if (!_resources.TryGetValue(font, out name))
{
name = NextFontName;
_resources[font] = name;
if (font.Reference == null)
Owner._irefTable.Add(font);
Fonts.Elements[name] = font.Reference;
}
return name;
}
/// <summary>
/// Adds the specified image to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddImage(PdfImage image)
{
string name;
if (!_resources.TryGetValue(image, out name))
{
name = NextImageName;
_resources[image] = name;
if (image.Reference == null)
Owner._irefTable.Add(image);
XObjects.Elements[name] = image.Reference;
}
return name;
}
/// <summary>
/// Adds the specified form object to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddForm(PdfFormXObject form)
{
string name;
if (!_resources.TryGetValue(form, out name))
{
name = NextFormName;
_resources[form] = name;
if (form.Reference == null)
Owner._irefTable.Add(form);
XObjects.Elements[name] = form.Reference;
}
return name;
}
/// <summary>
/// Adds the specified graphics state to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddExtGState(PdfExtGState extGState)
{
string name;
if (!_resources.TryGetValue(extGState, out name))
{
name = NextExtGStateName;
_resources[extGState] = name;
if (extGState.Reference == null)
Owner._irefTable.Add(extGState);
ExtGStates.Elements[name] = extGState.Reference;
}
return name;
}
/// <summary>
/// Adds the specified pattern to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddPattern(PdfShadingPattern pattern)
{
string name;
if (!_resources.TryGetValue(pattern, out name))
{
name = NextPatternName;
_resources[pattern] = name;
if (pattern.Reference == null)
Owner._irefTable.Add(pattern);
Patterns.Elements[name] = pattern.Reference;
}
return name;
}
/// <summary>
/// Adds the specified pattern to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddPattern(PdfTilingPattern pattern)
{
string name;
if (!_resources.TryGetValue(pattern, out name))
{
name = NextPatternName;
_resources[pattern] = name;
if (pattern.Reference == null)
Owner._irefTable.Add(pattern);
Patterns.Elements[name] = pattern.Reference;
}
return name;
}
/// <summary>
/// Adds the specified shading to this resource dictionary
/// and returns its local resource name.
/// </summary>
public string AddShading(PdfShading shading)
{
string name;
if (!_resources.TryGetValue(shading, out name))
{
name = NextShadingName;
_resources[shading] = name;
if (shading.Reference == null)
Owner._irefTable.Add(shading);
Shadings.Elements[name] = shading.Reference;
}
return name;
}
/// <summary>
/// Gets the fonts map.
/// </summary>
internal PdfResourceMap Fonts
{
get { return _fonts ?? (_fonts = (PdfResourceMap)Elements.GetValue(Keys.Font, VCF.Create)); }
}
PdfResourceMap _fonts;
/// <summary>
/// Gets the external objects map.
/// </summary>
internal PdfResourceMap XObjects
{
get { return _xObjects ?? (_xObjects = (PdfResourceMap)Elements.GetValue(Keys.XObject, VCF.Create)); }
}
PdfResourceMap _xObjects;
// TODO: make own class
internal PdfResourceMap ExtGStates
{
get
{
return _extGStates ?? (_extGStates = (PdfResourceMap)Elements.GetValue(Keys.ExtGState, VCF.Create));
}
}
PdfResourceMap _extGStates;
// TODO: make own class
internal PdfResourceMap ColorSpaces
{
get { return _colorSpaces ?? (_colorSpaces = (PdfResourceMap)Elements.GetValue(Keys.ColorSpace, VCF.Create)); }
}
PdfResourceMap _colorSpaces;
// TODO: make own class
internal PdfResourceMap Patterns
{
get { return _patterns ?? (_patterns = (PdfResourceMap) Elements.GetValue(Keys.Pattern, VCF.Create)); }
}
PdfResourceMap _patterns;
// TODO: make own class
internal PdfResourceMap Shadings
{
get { return _shadings ?? (_shadings = (PdfResourceMap) Elements.GetValue(Keys.Shading, VCF.Create)); }
}
PdfResourceMap _shadings;
// TODO: make own class
internal PdfResourceMap Properties
{
get {return _properties ?? (_properties = (PdfResourceMap) Elements.GetValue(Keys.Properties, VCF.Create));}
}
PdfResourceMap _properties;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextFontName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/F{0}", _fontNumber++))) { }
return name;
}
}
int _fontNumber;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextImageName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/I{0}", _imageNumber++))) { }
return name;
}
}
int _imageNumber;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextFormName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/Fm{0}", _formNumber++))) { }
return name;
}
}
int _formNumber;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextExtGStateName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/GS{0}", _extGStateNumber++))) { }
return name;
}
}
int _extGStateNumber;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextPatternName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/Pa{0}", _patternNumber++))) ;
return name;
}
}
int _patternNumber;
/// <summary>
/// Gets a new local name for this resource.
/// </summary>
string NextShadingName
{
get
{
string name;
while (ExistsResourceNames(name = string.Format("/Sh{0}", _shadingNumber++))) ;
return name;
}
}
int _shadingNumber;
/// <summary>
/// Check whether a resource name is already used in the context of this resource dictionary.
/// PDF4NET uses GUIDs as resource names, but I think this weapon is to heavy.
/// </summary>
internal bool ExistsResourceNames(string name)
{
// TODO: more precise: is this page imported and is PageOptions != Replace
// BUG:
//if (!Owner.IsImported)
// return false;
// Collect all resouce names of all imported resources.
if (_importedResourceNames == null)
{
_importedResourceNames = new Dictionary<string, object>();
if (Elements[Keys.Font] != null)
Fonts.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.XObject] != null)
XObjects.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.ExtGState] != null)
ExtGStates.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.ColorSpace] != null)
ColorSpaces.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.Pattern] != null)
Patterns.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.Shading] != null)
Shadings.CollectResourceNames(_importedResourceNames);
if (Elements[Keys.Properties] != null)
Properties.CollectResourceNames(_importedResourceNames);
}
return _importedResourceNames.ContainsKey(name);
// This is superfluous because PDFsharp resource names cannot be double.
// importedResourceNames.Add(name, null);
}
/// <summary>
/// All the names of imported resources.
/// </summary>
Dictionary<string, object> _importedResourceNames;
/// <summary>
/// Maps all PDFsharp resources to their local resource names.
/// </summary>
readonly Dictionary<PdfObject, string> _resources = new Dictionary<PdfObject, string>();
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public sealed class Keys : KeysBase
{
/// <summary>
/// (Optional) A dictionary that maps resource names to graphics state
/// parameter dictionaries.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string ExtGState = "/ExtGState";
/// <summary>
/// (Optional) A dictionary that maps each resource name to either the name of a
/// device-dependent color space or an array describing a color space.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string ColorSpace = "/ColorSpace";
/// <summary>
/// (Optional) A dictionary that maps each resource name to either the name of a
/// device-dependent color space or an array describing a color space.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string Pattern = "/Pattern";
/// <summary>
/// (Optional; PDF 1.3) A dictionary that maps resource names to shading dictionaries.
/// </summary>
[KeyInfo("1.3", KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string Shading = "/Shading";
/// <summary>
/// (Optional) A dictionary that maps resource names to external objects.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string XObject = "/XObject";
/// <summary>
/// (Optional) A dictionary that maps resource names to font dictionaries.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string Font = "/Font";
/// <summary>
/// (Optional) An array of predefined procedure set names.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string ProcSet = "/ProcSet";
/// <summary>
/// (Optional; PDF 1.2) A dictionary that maps resource names to property list
/// dictionaries for marked content.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfResourceMap))]
public const string Properties = "/Properties";
/// <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; }
}
}
}

View File

@@ -0,0 +1,258 @@
#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;
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
using PdfSharp.Drawing;
using PdfSharp.Drawing.Pdf;
using PdfSharp.Pdf.Internal;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a shading dictionary.
/// </summary>
public sealed class PdfShading : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfShading"/> class.
/// </summary>
public PdfShading(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Setups the shading from the specified brush.
/// </summary>
internal void SetupFromBrush(XLinearGradientBrush brush, XGraphicsPdfRenderer renderer)
{
if (brush == null)
throw new ArgumentNullException("brush");
PdfColorMode colorMode = _document.Options.ColorMode;
XColor color1 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color1);
XColor color2 = ColorSpaceHelper.EnsureColorMode(colorMode, brush._color2);
PdfDictionary function = new PdfDictionary();
Elements[Keys.ShadingType] = new PdfInteger(2);
if (colorMode != PdfColorMode.Cmyk)
Elements[Keys.ColorSpace] = new PdfName("/DeviceRGB");
else
Elements[Keys.ColorSpace] = new PdfName("/DeviceCMYK");
double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
if (brush._useRect)
{
XPoint pt1 = renderer.WorldToView(brush._rect.TopLeft);
XPoint pt2 = renderer.WorldToView(brush._rect.BottomRight);
switch (brush._linearGradientMode)
{
case XLinearGradientMode.Horizontal:
x1 = pt1.X;
y1 = pt1.Y;
x2 = pt2.X;
y2 = pt1.Y;
break;
case XLinearGradientMode.Vertical:
x1 = pt1.X;
y1 = pt1.Y;
x2 = pt1.X;
y2 = pt2.Y;
break;
case XLinearGradientMode.ForwardDiagonal:
x1 = pt1.X;
y1 = pt1.Y;
x2 = pt2.X;
y2 = pt2.Y;
break;
case XLinearGradientMode.BackwardDiagonal:
x1 = pt2.X;
y1 = pt1.Y;
x2 = pt1.X;
y2 = pt2.Y;
break;
}
}
else
{
XPoint pt1 = renderer.WorldToView(brush._point1);
XPoint pt2 = renderer.WorldToView(brush._point2);
x1 = pt1.X;
y1 = pt1.Y;
x2 = pt2.X;
y2 = pt2.Y;
}
const string format = Config.SignificantFigures3;
Elements[Keys.Coords] = new PdfLiteral("[{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "}]", x1, y1, x2, y2);
//Elements[Keys.Background] = new PdfRawItem("[0 1 1]");
//Elements[Keys.Domain] =
Elements[Keys.Function] = function;
//Elements[Keys.Extend] = new PdfRawItem("[true true]");
string clr1 = "[" + PdfEncoders.ToString(color1, colorMode) + "]";
string clr2 = "[" + PdfEncoders.ToString(color2, colorMode) + "]";
function.Elements["/FunctionType"] = new PdfInteger(2);
function.Elements["/C0"] = new PdfLiteral(clr1);
function.Elements["/C1"] = new PdfLiteral(clr2);
function.Elements["/Domain"] = new PdfLiteral("[0 1]");
function.Elements["/N"] = new PdfInteger(1);
}
/// <summary>
/// Common keys for all streams.
/// </summary>
internal sealed class Keys : KeysBase
{
/// <summary>
/// (Required) The shading type:
/// 1 Function-based shading
/// 2 Axial shading
/// 3 Radial shading
/// 4 Free-form Gouraud-shaded triangle mesh
/// 5 Lattice-form Gouraud-shaded triangle mesh
/// 6 Coons patch mesh
/// 7 Tensor-product patch mesh
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string ShadingType = "/ShadingType";
/// <summary>
/// (Required) The color space in which color values are expressed. This may be any device,
/// CIE-based, or special color space except a Pattern space.
/// </summary>
[KeyInfo(KeyType.NameOrArray | KeyType.Required)]
public const string ColorSpace = "/ColorSpace";
/// <summary>
/// (Optional) An array of color components appropriate to the color space, specifying
/// a single background color value. If present, this color is used, before any painting
/// operation involving the shading, to fill those portions of the area to be painted
/// that lie outside the bounds of the shading object. In the opaque imaging model,
/// the effect is as if the painting operation were performed twice: first with the
/// background color and then with the shading.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Background = "/Background";
/// <summary>
/// (Optional) An array of four numbers giving the left, bottom, right, and top coordinates,
/// respectively, of the shading<6E>s bounding box. The coordinates are interpreted in the
/// shading<6E>s target coordinate space. If present, this bounding box is applied as a temporary
/// clipping boundary when the shading is painted, in addition to the current clipping path
/// and any other clipping boundaries in effect at that time.
/// </summary>
[KeyInfo(KeyType.Rectangle | KeyType.Optional)]
public const string BBox = "/BBox";
/// <summary>
/// (Optional) A flag indicating whether to filter the shading function to prevent aliasing
/// artifacts. The shading operators sample shading functions at a rate determined by the
/// resolution of the output device. Aliasing can occur if the function is not smooth<74>that
/// is, if it has a high spatial frequency relative to the sampling rate. Anti-aliasing can
/// be computationally expensive and is usually unnecessary, since most shading functions
/// are smooth enough or are sampled at a high enough frequency to avoid aliasing effects.
/// Anti-aliasing may not be implemented on some output devices, in which case this flag
/// is ignored.
/// Default value: false.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string AntiAlias = "/AntiAlias";
// ---- Type 2 ----------------------------------------------------------
/// <summary>
/// (Required) An array of four numbers [x0 y0 x1 y1] specifying the starting and
/// ending coordinates of the axis, expressed in the shading<6E>s target coordinate space.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Required)]
public const string Coords = "/Coords";
/// <summary>
/// (Optional) An array of two numbers [t0 t1] specifying the limiting values of a
/// parametric variable t. The variable is considered to vary linearly between these
/// two values as the color gradient varies between the starting and ending points of
/// the axis. The variable t becomes the input argument to the color function(s).
/// Default value: [0.0 1.0].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Domain = "/Domain";
/// <summary>
/// (Required) A 1-in, n-out function or an array of n 1-in, 1-out functions (where n
/// is the number of color components in the shading dictionary<72>s color space). The
/// function(s) are called with values of the parametric variable t in the domain defined
/// by the Domain entry. Each function<6F>s domain must be a superset of that of the shading
/// dictionary. If the value returned by the function for a given color component is out
/// of range, it is adjusted to the nearest valid value.
/// </summary>
[KeyInfo(KeyType.Function | KeyType.Required)]
public const string Function = "/Function";
/// <summary>
/// (Optional) An array of two boolean values specifying whether to extend the shading
/// beyond the starting and ending points of the axis, respectively.
/// Default value: [false false].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Extend = "/Extend";
/// <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; }
}
}
}

View File

@@ -0,0 +1,132 @@
#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;
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
using PdfSharp.Drawing;
using PdfSharp.Drawing.Pdf;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a shading pattern dictionary.
/// </summary>
public sealed class PdfShadingPattern : PdfDictionaryWithContentStream
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfShadingPattern"/> class.
/// </summary>
public PdfShadingPattern(PdfDocument document)
: base(document)
{
Elements.SetName(Keys.Type, "/Pattern");
Elements[Keys.PatternType] = new PdfInteger(2);
}
/// <summary>
/// Setups the shading pattern from the specified brush.
/// </summary>
internal void SetupFromBrush(XLinearGradientBrush brush, XMatrix matrix, XGraphicsPdfRenderer renderer)
{
if (brush == null)
throw new ArgumentNullException("brush");
PdfShading shading = new PdfShading(_document);
shading.SetupFromBrush(brush, renderer);
Elements[Keys.Shading] = shading;
//Elements[Keys.Matrix] = new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]");
Elements.SetMatrix(Keys.Matrix, matrix);
}
/// <summary>
/// Common keys for all streams.
/// </summary>
internal sealed new class Keys : PdfDictionaryWithContentStream.Keys
{
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes; if present,
/// must be Pattern for a pattern dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string Type = "/Type";
/// <summary>
/// (Required) A code identifying the type of pattern that this dictionary describes;
/// must be 2 for a shading pattern.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string PatternType = "/PatternType";
/// <summary>
/// (Required) A shading object (see below) defining the shading pattern<72>s gradient fill.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required)]
public const string Shading = "/Shading";
/// <summary>
/// (Optional) An array of six numbers specifying the pattern matrix.
/// Default value: the identity matrix [1 0 0 1 0 0].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Matrix = "/Matrix";
/// <summary>
/// (Optional) A graphics state parameter dictionary containing graphics state parameters
/// to be put into effect temporarily while the shading pattern is painted. Any parameters
/// that are not so specified are inherited from the graphics state that was in effect
/// at the beginning of the content stream in which the pattern is defined as a resource.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional)]
public const string ExtGState = "/ExtGState";
/// <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; }
}
}
}

View File

@@ -0,0 +1,110 @@
#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
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF soft mask.
/// </summary>
public class PdfSoftMask : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfXObject"/> class.
/// </summary>
/// <param name="document">The document that owns the object.</param>
public PdfSoftMask(PdfDocument document)
: base(document)
{
Elements.SetName(Keys.Type, "/Mask");
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public class Keys : KeysBase
{
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes;
/// if present, must be Mask for a soft-mask dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional, FixedValue = "Mask")]
public const string Type = "/Type";
/// <summary>
/// (Required) A subtype specifying the method to be used in deriving the mask values
/// from the transparency group specified by the G entry:
/// Alpha: Use the group<75>s computed alpha, disregarding its color.
/// Luminosity: Convert the group<75>s computed color to a single-component luminosity value.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string S = "/S";
/// <summary>
/// (Required) A transparency group XObject to be used as the source of alpha
/// or color values for deriving the mask. If the subtype S is Luminosity, the
/// group attributes dictionary must contain a CS entry defining the color space
/// in which the compositing computation is to be performed.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Required)]
public const string G = "/G";
/// <summary>
/// (Optional) An array of component values specifying the color to be used
/// as the backdrop against which to composite the transparency group XObject G.
/// This entry is consulted only if the subtype S is Luminosity. The array consists of
/// n numbers, where n is the number of components in the color space specified
/// by the CS entry in the group attributes dictionary.
/// Default value: the color space<63>s initial value, representing black.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string BC = "/BC";
/// <summary>
/// (Optional) A function object specifying the transfer function to be used in
/// deriving the mask values. The function accepts one input, the computed
/// group alpha or luminosity (depending on the value of the subtype S), and
/// returns one output, the resulting mask value. Both the input and output
/// must be in the range 0.0 to 1.0; if the computed output falls outside this
/// range, it is forced to the nearest valid value. The name Identity may be
/// specified in place of a function object to designate the identity function.
/// Default value: Identity.
/// </summary>
[KeyInfo(KeyType.FunctionOrName | KeyType.Optional)]
public const string TR = "/TR";
}
}
}

View File

@@ -0,0 +1,177 @@
#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
#if GDI
using System.Drawing;
using System.Drawing.Imaging;
#endif
#if WPF
using System.Windows.Media;
#endif
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a tiling pattern dictionary.
/// </summary>
public sealed class PdfTilingPattern : PdfDictionaryWithContentStream
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfShadingPattern"/> class.
/// </summary>
public PdfTilingPattern(PdfDocument document)
: base(document)
{
Elements.SetName(Keys.Type, "/Pattern");
Elements[Keys.PatternType] = new PdfInteger(1);
}
///// <summary>
///// Setups the shading pattern from the specified brush.
///// </summary>
//public void SetupFromBrush(XLinearGradientBrush brush, XMatrix matrix)
//{
// if (brush == null)
// throw new ArgumentNullException("brush");
// PdfShading shading = new PdfShading(document);
// shading.SetupFromBrush(brush);
// Elements[Keys.Shading] = shading;
// Elements[Keys.Matrix] = new PdfLiteral("[" + PdfEncoders.ToString(matrix) + "]");
//}
/// <summary>
/// Common keys for all streams.
/// </summary>
internal sealed new class Keys : PdfDictionaryWithContentStream.Keys
{
/// <summary>
/// (Optional) The type of PDF object that this dictionary describes; if present,
/// must be Pattern for a pattern dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public const string Type = "/Type";
/// <summary>
/// (Required) A code identifying the type of pattern that this dictionary describes;
/// must be 1 for a tiling pattern.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string PatternType = "/PatternType";
/// <summary>
/// (Required) A code that determines how the color of the pattern cell is to be specified:
/// 1: Colored tiling pattern. The pattern<72>s content stream specifies the colors used to
/// paint the pattern cell. When the content stream begins execution, the current color
/// is the one that was initially in effect in the pattern<72>s parent content stream.
/// 2: Uncolored tiling pattern. The pattern<72>s content stream does not specify any color
/// information. Instead, the entire pattern cell is painted with a separately specified color
/// each time the pattern is used. Essentially, the content stream describes a stencil
/// through which the current color is to be poured. The content stream must not invoke
/// operators that specify colors or other color-related parameters in the graphics state;
/// otherwise, an error occurs. The content stream may paint an image mask, however,
/// since it does not specify any color information.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string PaintType = "/PaintType";
/// <summary>
/// (Required) A code that controls adjustments to the spacing of tiles relative to the device
/// pixel grid:
/// 1: Constant spacing. Pattern cells are spaced consistently<6C>that is, by a multiple of a
/// device pixel. To achieve this, the application may need to distort the pattern cell slightly
/// by making small adjustments to XStep, YStep, and the transformation matrix. The amount
/// of distortion does not exceed 1 device pixel.
/// 2: No distortion. The pattern cell is not distorted, but the spacing between pattern cells
/// may vary by as much as 1 device pixel, both horizontally and vertically, when the pattern
/// is painted. This achieves the spacing requested by XStep and YStep on average but not
/// necessarily for each individual pattern cell.
/// 3: Constant spacing and faster tiling. Pattern cells are spaced consistently as in tiling
/// type 1 but with additional distortion permitted to enable a more efficient implementation.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string TilingType = "/TilingType";
/// <summary>
/// (Required) An array of four numbers in the pattern coordinate system giving the
/// coordinates of the left, bottom, right, and top edges, respectively, of the pattern
/// cell<6C>s bounding box. These boundaries are used to clip the pattern cell.
/// </summary>
[KeyInfo(KeyType.Rectangle | KeyType.Optional)]
public const string BBox = "/BBox";
/// <summary>
/// (Required) The desired horizontal spacing between pattern cells, measured in the
/// pattern coordinate system.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string XStep = "/XStep";
/// <summary>
/// (Required) The desired vertical spacing between pattern cells, measured in the pattern
/// coordinate system. Note that XStep and YStep may differ from the dimensions of the
/// pattern cell implied by the BBox entry. This allows tiling with irregularly shaped figures.
/// XStep and YStep may be either positive or negative but not zero.
/// </summary>
[KeyInfo(KeyType.Real | KeyType.Required)]
public const string YStep = "/YStep";
/// <summary>
/// (Required) A resource dictionary containing all of the named resources required by
/// the pattern<72>s content stream (see Section 3.7.2, <20>Resource Dictionaries<65>).
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required)]
public new const string Resources = "/Resources";
/// <summary>
/// (Optional) An array of six numbers specifying the pattern matrix.
/// Default value: the identity matrix [1 0 0 1 0 0].
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string Matrix = "/Matrix";
/// <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; }
}
}
}

View File

@@ -0,0 +1,148 @@
#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.Collections.Generic;
using System.Text;
using System.IO;
using PdfSharp.Fonts;
using PdfSharp.Pdf.Filters;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a ToUnicode map for composite font.
/// </summary>
internal sealed class PdfToUnicodeMap : PdfDictionary
{
public PdfToUnicodeMap(PdfDocument document)
: base(document)
{ }
public PdfToUnicodeMap(PdfDocument document, CMapInfo cmapInfo)
: base(document)
{
_cmapInfo = cmapInfo;
}
/// <summary>
/// Gets or sets the CMap info.
/// </summary>
public CMapInfo CMapInfo
{
get { return _cmapInfo; }
set { _cmapInfo = value; }
}
CMapInfo _cmapInfo;
/// <summary>
/// Creates the ToUnicode map from the CMapInfo.
/// </summary>
internal override void PrepareForSave()
{
base.PrepareForSave();
// This code comes literally from PDF Reference
string prefix =
"/CIDInit /ProcSet findresource begin\n" +
"12 dict begin\n" +
"begincmap\n" +
"/CIDSystemInfo << /Registry (Adobe)/Ordering (UCS)/Supplement 0>> def\n" +
"/CMapName /Adobe-Identity-UCS def /CMapType 2 def\n";
string suffix = "endcmap CMapName currentdict /CMap defineresource pop end end";
Dictionary<int, char> glyphIndexToCharacter = new Dictionary<int, char>();
int lowIndex = 65536, hiIndex = -1;
foreach (KeyValuePair<char, int> entry in _cmapInfo.CharacterToGlyphIndex)
{
int index = (int)entry.Value;
lowIndex = Math.Min(lowIndex, index);
hiIndex = Math.Max(hiIndex, index);
//glyphIndexToCharacter.Add(index, entry.Key);
glyphIndexToCharacter[index] = entry.Key;
}
MemoryStream ms = new MemoryStream();
#if !SILVERLIGHT && !NETFX_CORE
StreamWriter wrt = new StreamWriter(ms, Encoding.ASCII);
#else
StreamWriter wrt = new StreamWriter(ms, Encoding.UTF8);
#endif
wrt.Write(prefix);
wrt.WriteLine("1 begincodespacerange");
wrt.WriteLine(String.Format("<{0:X4}><{1:X4}>", lowIndex, hiIndex));
wrt.WriteLine("endcodespacerange");
// Sorting seems not necessary. The limit is 100 entries, we will see.
wrt.WriteLine(String.Format("{0} beginbfrange", glyphIndexToCharacter.Count));
foreach (KeyValuePair<int, char> entry in glyphIndexToCharacter)
wrt.WriteLine(String.Format("<{0:X4}><{0:X4}><{1:X4}>", entry.Key, (int)entry.Value));
wrt.WriteLine("endbfrange");
wrt.Write(suffix);
#if !UWP
wrt.Close();
#else
wrt.Dispose();
#endif
// Compress like content streams
byte[] bytes = ms.ToArray();
#if !UWP
ms.Close();
#else
ms.Dispose();
#endif
if (Owner.Options.CompressContentStreams)
{
Elements.SetName("/Filter", "/FlateDecode");
bytes = Filtering.FlateDecode.Encode(bytes, _document.Options.FlateEncodeMode);
}
//PdfStream stream = CreateStream(bytes);
else
{
Elements.Remove("/Filter");
}
if (Stream == null)
CreateStream(bytes);
else
{
Stream.Value = bytes;
Elements.SetInteger(PdfStream.Keys.Length, Stream.Length);
}
}
public sealed class Keys : PdfStream.Keys
{
// No new keys.
}
}
}

View File

@@ -0,0 +1,297 @@
#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.Pdf.IO;
using PdfSharp.Pdf.Security;
using PdfSharp.Pdf.Internal;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF trailer dictionary. Even though trailers are dictionaries they never have a cross
/// reference entry in PdfReferenceTable.
/// </summary>
internal class PdfTrailer : PdfDictionary // Reference: 3.4.4 File Trailer / Page 96
{
/// <summary>
/// Initializes a new instance of PdfTrailer.
/// </summary>
public PdfTrailer(PdfDocument document)
: base(document)
{
_document = document;
}
/// <summary>
/// Initializes a new instance of the <see cref="PdfTrailer"/> class from a <see cref="PdfCrossReferenceStream"/>.
/// </summary>
public PdfTrailer(PdfCrossReferenceStream trailer)
: base(trailer._document)
{
_document = trailer._document;
// /ID [<09F877EBF282E9408ED1882A9A21D9F2><2A4938E896006F499AC1C2EA7BFB08E4>]
// /Info 7 0 R
// /Root 1 0 R
// /Size 10
PdfReference iref = trailer.Elements.GetReference(Keys.Info);
if (iref != null)
Elements.SetReference(Keys.Info, iref);
Elements.SetReference(Keys.Root, trailer.Elements.GetReference(Keys.Root));
Elements.SetInteger(Keys.Size, trailer.Elements.GetInteger(Keys.Size));
PdfArray id = trailer.Elements.GetArray(Keys.ID);
if (id != null)
Elements.SetValue(Keys.ID, id);
}
public int Size
{
get { return Elements.GetInteger(Keys.Size); }
set { Elements.SetInteger(Keys.Size, value); }
}
// TODO: needed when linearized...
//public int Prev
//{
// get {return Elements.GetInteger(Keys.Prev);}
//}
public PdfDocumentInformation Info
{
get { return (PdfDocumentInformation)Elements.GetValue(Keys.Info, VCF.CreateIndirect); }
}
/// <summary>
/// (Required; must be an indirect reference)
/// The catalog dictionary for the PDF document contained in the file.
/// </summary>
public PdfCatalog Root
{
get { return (PdfCatalog)Elements.GetValue(PdfTrailer.Keys.Root, VCF.CreateIndirect); }
}
/// <summary>
/// Gets the first or second document identifier.
/// </summary>
public string GetDocumentID(int index)
{
if (index < 0 || index > 1)
throw new ArgumentOutOfRangeException("index", index, "Index must be 0 or 1.");
PdfArray array = Elements[Keys.ID] as PdfArray;
if (array == null || array.Elements.Count < 2)
return "";
PdfItem item = array.Elements[index];
if (item is PdfString)
return ((PdfString)item).Value;
return "";
}
/// <summary>
/// Sets the first or second document identifier.
/// </summary>
public void SetDocumentID(int index, string value)
{
if (index < 0 || index > 1)
throw new ArgumentOutOfRangeException("index", index, "Index must be 0 or 1.");
PdfArray array = Elements[Keys.ID] as PdfArray;
if (array == null || array.Elements.Count < 2)
array = CreateNewDocumentIDs();
array.Elements[index] = new PdfString(value, PdfStringFlags.HexLiteral);
}
/// <summary>
/// Creates and sets two identical new document IDs.
/// </summary>
internal PdfArray CreateNewDocumentIDs()
{
PdfArray array = new PdfArray(_document);
byte[] docID = Guid.NewGuid().ToByteArray();
string id = PdfEncoders.RawEncoding.GetString(docID, 0, docID.Length);
array.Elements.Add(new PdfString(id, PdfStringFlags.HexLiteral));
array.Elements.Add(new PdfString(id, PdfStringFlags.HexLiteral));
Elements[Keys.ID] = array;
return array;
}
/// <summary>
/// Gets the standard security handler.
/// </summary>
public PdfStandardSecurityHandler SecurityHandler
{
get
{
if (_securityHandler == null)
_securityHandler = (PdfStandardSecurityHandler)Elements.GetValue(Keys.Encrypt, VCF.CreateIndirect);
return _securityHandler;
}
}
internal PdfStandardSecurityHandler _securityHandler;
internal override void WriteObject(PdfWriter writer)
{
// Delete /XRefStm entry, if any.
// HACK:
_elements.Remove(Keys.XRefStm);
// Don't encrypt myself
PdfStandardSecurityHandler securityHandler = writer.SecurityHandler;
writer.SecurityHandler = null;
base.WriteObject(writer);
writer.SecurityHandler = securityHandler;
}
/// <summary>
/// Replace temporary irefs by their correct counterparts from the iref table.
/// </summary>
internal void Finish()
{
// /Root
PdfReference iref = _document._trailer.Elements[Keys.Root] as PdfReference;
if (iref != null && iref.Value == null)
{
iref = _document._irefTable[iref.ObjectID];
Debug.Assert(iref.Value != null);
_document._trailer.Elements[Keys.Root] = iref;
}
// /Info
iref = _document._trailer.Elements[PdfTrailer.Keys.Info] as PdfReference;
if (iref != null && iref.Value == null)
{
iref = _document._irefTable[iref.ObjectID];
Debug.Assert(iref.Value != null);
_document._trailer.Elements[Keys.Info] = iref;
}
// /Encrypt
iref = _document._trailer.Elements[Keys.Encrypt] as PdfReference;
if (iref != null)
{
iref = _document._irefTable[iref.ObjectID];
Debug.Assert(iref.Value != null);
_document._trailer.Elements[Keys.Encrypt] = iref;
// The encryption dictionary (security handler) was read in before the XRefTable construction
// was completed. The next lines fix that state (it took several hours to find these bugs...).
iref.Value = _document._trailer._securityHandler;
_document._trailer._securityHandler.Reference = iref;
iref.Value.Reference = iref;
}
Elements.Remove(Keys.Prev);
Debug.Assert(_document._irefTable.IsUnderConstruction == false);
_document._irefTable.IsUnderConstruction = false;
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
internal class Keys : KeysBase // Reference: TABLE 3.13 Entries in the file trailer dictionary / Page 97
{
/// <summary>
/// (Required; must not be an indirect reference) The total number of entries in the file<6C>s
/// cross-reference table, as defined by the combination of the original section and all
/// update sections. Equivalently, this value is 1 greater than the highest object number
/// used in the file.
/// Note: Any object in a cross-reference section whose number is greater than this value is
/// ignored and considered missing.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Required)]
public const string Size = "/Size";
/// <summary>
/// (Present only if the file has more than one cross-reference section; must not be an indirect
/// reference) The byte offset from the beginning of the file to the beginning of the previous
/// cross-reference section.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string Prev = "/Prev";
/// <summary>
/// (Required; must be an indirect reference) The catalog dictionary for the PDF document
/// contained in the file.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Required, typeof(PdfCatalog))]
public const string Root = "/Root";
/// <summary>
/// (Required if document is encrypted; PDF 1.1) The document<6E>s encryption dictionary.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfStandardSecurityHandler))]
public const string Encrypt = "/Encrypt";
/// <summary>
/// (Optional; must be an indirect reference) The document<6E>s information dictionary.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.Optional, typeof(PdfDocumentInformation))]
public const string Info = "/Info";
/// <summary>
/// (Optional, but strongly recommended; PDF 1.1) An array of two strings constituting
/// a file identifier for the file. Although this entry is optional,
/// its absence might prevent the file from functioning in some workflows
/// that depend on files being uniquely identified.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Optional)]
public const string ID = "/ID";
/// <summary>
/// (Optional) The byte offset from the beginning of the file of a cross-reference stream.
/// </summary>
[KeyInfo(KeyType.Integer | KeyType.Optional)]
public const string XRefStm = "/XRefStm";
/// <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; }
}
}
}

View File

@@ -0,0 +1,129 @@
#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
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a PDF transparency group XObject.
/// </summary>
public sealed class PdfTransparencyGroupAttributes : PdfGroupAttributes
{
internal PdfTransparencyGroupAttributes(PdfDocument thisDocument)
: base(thisDocument)
{
Elements.SetName(Keys.S, "/Transparency");
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public sealed new class Keys : PdfGroupAttributes.Keys
{
/// <summary>
/// (Sometimes required, as discussed below)
/// The group color space, which is used for the following purposes:
/// <20> As the color space into which colors are converted when painted into the group
/// <20> As the blending color space in which objects are composited within the group
/// <20> As the color space of the group as a whole when it in turn is painted as an object onto its backdrop
/// The group color space may be any device or CIE-based color space that
/// treats its components as independent additive or subtractive values in the
/// range 0.0 to 1.0, subject to the restrictions described in Section 7.2.3, <20>Blending Color Space.<2E>
/// These restrictions exclude Lab and lightness-chromaticity ICCBased color spaces,
/// as well as the special color spaces Pattern, Indexed, Separation, and DeviceN.
/// Device color spaces are subject to remapping according to the DefaultGray,
/// DefaultRGB, and DefaultCMYK entries in the ColorSpace subdictionary of the
/// current resource dictionary.
/// Ordinarily, the CS entry is allowed only for isolated transparency groups
/// (those for which I, below, is true), and even then it is optional. However,
/// this entry is required in the group attributes dictionary for any transparency
/// group XObject that has no parent group or page from which to inherit <20> in
/// particular, one that is the value of the G entry in a soft-mask dictionary of
/// subtype Luminosity.
/// In addition, it is always permissible to specify CS in the group attributes
/// dictionary associated with a page object, even if I is false or absent. In the
/// normal case in which the page is imposed directly on the output medium,
/// the page group is effectively isolated regardless of the I value, and the
/// specified CS value is therefore honored. But if the page is in turn used as an
/// element of some other page and if the group is non-isolated, CS is ignored
/// and the color space is inherited from the actual backdrop with which the
/// page is composited.
/// Default value: the color space of the parent group or page into which this
/// transparency group is painted. (The parent<6E>s color space in turn can be
/// either explicitly specified or inherited.)
/// </summary>
[KeyInfo(KeyType.NameOrArray | KeyType.Optional)]
public const string CS = "/CS";
/// <summary>
/// (Optional) A flag specifying whether the transparency group is isolated.
/// If this flag is true, objects within the group are composited against a fully
/// transparent initial backdrop; if false, they are composited against the
/// group<75>s backdrop.
/// Default value: false.
/// In the group attributes dictionary for a page, the interpretation of this
/// entry is slightly altered. In the normal case in which the page is imposed
/// directly on the output medium, the page group is effectively isolated and
/// the specified I value is ignored. But if the page is in turn used as an
/// element of some other page, it is treated as if it were a transparency
/// group XObject; the I value is interpreted in the normal way to determine
/// whether the page group is isolated.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string I = "/I";
/// <summary>
/// (Optional) A flag specifying whether the transparency group is a knockout
/// group. If this flag is false, later objects within the group are composited
/// with earlier ones with which they overlap; if true, they are composited with
/// the group<75>s initial backdrop and overwrite (<28>knock out<75>) any earlier
/// overlapping objects.
/// Default value: false.
/// </summary>
[KeyInfo(KeyType.Boolean | KeyType.Optional)]
public const string K = "/K";
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static new 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; }
}
}
}

View File

@@ -0,0 +1,254 @@
#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.Diagnostics;
using PdfSharp.Fonts;
using PdfSharp.Fonts.OpenType;
using PdfSharp.Drawing;
using PdfSharp.Pdf.Filters;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a TrueType font.
/// </summary>
internal class PdfTrueTypeFont : PdfFont
{
public PdfTrueTypeFont(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Initializes a new instance of PdfTrueTypeFont from an XFont.
/// </summary>
public PdfTrueTypeFont(PdfDocument document, XFont font)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/TrueType");
// TrueType with WinAnsiEncoding only.
OpenTypeDescriptor ttDescriptor = (OpenTypeDescriptor)FontDescriptorCache.GetOrCreateDescriptorFor(font);
FontDescriptor = new PdfFontDescriptor(document, ttDescriptor);
_fontOptions = font.PdfOptions;
Debug.Assert(_fontOptions != null);
//cmapInfo = new CMapInfo(null/*ttDescriptor*/);
_cmapInfo = new CMapInfo(ttDescriptor);
BaseFont = font.GlyphTypeface.GetBaseName();
if (_fontOptions.FontEmbedding == PdfFontEmbedding.Always)
BaseFont = PdfFont.CreateEmbeddedFontSubsetName(BaseFont);
FontDescriptor.FontName = BaseFont;
Debug.Assert(_fontOptions.FontEncoding == PdfFontEncoding.WinAnsi);
if (!IsSymbolFont)
Encoding = "/WinAnsiEncoding";
Owner._irefTable.Add(FontDescriptor);
Elements[Keys.FontDescriptor] = FontDescriptor.Reference;
FontEncoding = font.PdfOptions.FontEncoding;
}
XPdfFontOptions FontOptions
{
get { return _fontOptions; }
}
readonly XPdfFontOptions _fontOptions;
public string BaseFont
{
get { return Elements.GetName(Keys.BaseFont); }
set { Elements.SetName(Keys.BaseFont, value); }
}
public int FirstChar
{
get { return Elements.GetInteger(Keys.FirstChar); }
set { Elements.SetInteger(Keys.FirstChar, value); }
}
public int LastChar
{
get { return Elements.GetInteger(Keys.LastChar); }
set { Elements.SetInteger(Keys.LastChar, value); }
}
public PdfArray Widths
{
get { return (PdfArray)Elements.GetValue(Keys.Widths, VCF.Create); }
}
public string Encoding
{
get { return Elements.GetName(Keys.Encoding); }
set { Elements.SetName(Keys.Encoding, value); }
}
/// <summary>
/// Prepares the object to get saved.
/// </summary>
internal override void PrepareForSave()
{
base.PrepareForSave();
// Fonts are always embedded.
OpenTypeFontface subSet = FontDescriptor._descriptor.FontFace.CreateFontSubSet(_cmapInfo.GlyphIndices, false);
byte[] fontData = subSet.FontSource.Bytes;
PdfDictionary fontStream = new PdfDictionary(Owner);
Owner.Internals.AddObject(fontStream);
FontDescriptor.Elements[PdfFontDescriptor.Keys.FontFile2] = fontStream.Reference;
fontStream.Elements["/Length1"] = new PdfInteger(fontData.Length);
if (!Owner.Options.NoCompression)
{
fontData = Filtering.FlateDecode.Encode(fontData, _document.Options.FlateEncodeMode);
fontStream.Elements["/Filter"] = new PdfName("/FlateDecode");
}
fontStream.Elements["/Length"] = new PdfInteger(fontData.Length);
fontStream.CreateStream(fontData);
FirstChar = 0;
LastChar = 255;
PdfArray width = Widths;
//width.Elements.Clear();
for (int idx = 0; idx < 256; idx++)
width.Elements.Add(new PdfInteger(FontDescriptor._descriptor.Widths[idx]));
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public new sealed class Keys : PdfFont.Keys
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Font for a font dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Font")]
public new const string Type = "/Type";
/// <summary>
/// (Required) The type of font; must be TrueType for a TrueType font.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string Subtype = "/Subtype";
/// <summary>
/// (Required in PDF 1.0; optional otherwise) The name by which this font is
/// referenced in the Font subdictionary of the current resource dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Name = "/Name";
/// <summary>
/// (Required) The PostScript name of the font. For Type 1 fonts, this is usually
/// the value of the FontName entry in the font program; for more information.
/// The Post-Script name of the font can be used to find the font<6E>s definition in
/// the consumer application or its environment. It is also the name that is used when
/// printing to a PostScript output device.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string BaseFont = "/BaseFont";
/// <summary>
/// (Required except for the standard 14 fonts) The first character code defined
/// in the font<6E>s Widths array.
/// </summary>
[KeyInfo(KeyType.Integer)]
public const string FirstChar = "/FirstChar";
/// <summary>
/// (Required except for the standard 14 fonts) The last character code defined
/// in the font<6E>s Widths array.
/// </summary>
[KeyInfo(KeyType.Integer)]
public const string LastChar = "/LastChar";
/// <summary>
/// (Required except for the standard 14 fonts; indirect reference preferred)
/// An array of (LastChar - FirstChar + 1) widths, each element being the glyph width
/// for the character code that equals FirstChar plus the array index. For character
/// codes outside the range FirstChar to LastChar, the value of MissingWidth from the
/// FontDescriptor entry for this font is used. The glyph widths are measured in units
/// in which 1000 units corresponds to 1 unit in text space. These widths must be
/// consistent with the actual widths given in the font program.
/// </summary>
[KeyInfo(KeyType.Array, typeof(PdfArray))]
public const string Widths = "/Widths";
/// <summary>
/// (Required except for the standard 14 fonts; must be an indirect reference)
/// A font descriptor describing the font<6E>s metrics other than its glyph widths.
/// Note: For the standard 14 fonts, the entries FirstChar, LastChar, Widths, and
/// FontDescriptor must either all be present or all be absent. Ordinarily, they are
/// absent; specifying them enables a standard font to be overridden.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.MustBeIndirect, typeof(PdfFontDescriptor))]
public new const string FontDescriptor = "/FontDescriptor";
/// <summary>
/// (Optional) A specification of the font<6E>s character encoding if different from its
/// built-in encoding. The value of Encoding is either the name of a predefined
/// encoding (MacRomanEncoding, MacExpertEncoding, or WinAnsiEncoding, as described in
/// Appendix D) or an encoding dictionary that specifies differences from the font<6E>s
/// built-in encoding or from a specified predefined encoding.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Dictionary)]
public const string Encoding = "/Encoding";
/// <summary>
/// (Optional; PDF 1.2) A stream containing a CMap file that maps character
/// codes to Unicode values.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string ToUnicode = "/ToUnicode";
/// <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; }
}
}
}

View File

@@ -0,0 +1,241 @@
#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.Diagnostics;
using System.Text;
using PdfSharp.Fonts;
using PdfSharp.Fonts.OpenType;
using PdfSharp.Drawing;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Represents a composite font. Used for Unicode encoding.
/// </summary>
internal sealed class PdfType0Font : PdfFont
{
public PdfType0Font(PdfDocument document)
: base(document)
{ }
public PdfType0Font(PdfDocument document, XFont font, bool vertical)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/Type0");
Elements.SetName(Keys.Encoding, vertical ? "/Identity-V" : "/Identity-H");
OpenTypeDescriptor ttDescriptor = (OpenTypeDescriptor)FontDescriptorCache.GetOrCreateDescriptorFor(font);
FontDescriptor = new PdfFontDescriptor(document, ttDescriptor);
_fontOptions = font.PdfOptions;
Debug.Assert(_fontOptions != null);
_cmapInfo = new CMapInfo(ttDescriptor);
_descendantFont = new PdfCIDFont(document, FontDescriptor, font);
_descendantFont.CMapInfo = _cmapInfo;
// Create ToUnicode map
_toUnicode = new PdfToUnicodeMap(document, _cmapInfo);
document.Internals.AddObject(_toUnicode);
Elements.Add(Keys.ToUnicode, _toUnicode);
BaseFont = font.GlyphTypeface.GetBaseName();
// CID fonts are always embedded
BaseFont = PdfFont.CreateEmbeddedFontSubsetName(BaseFont);
FontDescriptor.FontName = BaseFont;
_descendantFont.BaseFont = BaseFont;
PdfArray descendantFonts = new PdfArray(document);
Owner._irefTable.Add(_descendantFont);
descendantFonts.Elements.Add(_descendantFont.Reference);
Elements[Keys.DescendantFonts] = descendantFonts;
}
public PdfType0Font(PdfDocument document, string idName, byte[] fontData, bool vertical)
: base(document)
{
Elements.SetName(Keys.Type, "/Font");
Elements.SetName(Keys.Subtype, "/Type0");
Elements.SetName(Keys.Encoding, vertical ? "/Identity-V" : "/Identity-H");
OpenTypeDescriptor ttDescriptor = (OpenTypeDescriptor)FontDescriptorCache.GetOrCreateDescriptor(idName, fontData);
FontDescriptor = new PdfFontDescriptor(document, ttDescriptor);
_fontOptions = new XPdfFontOptions(PdfFontEncoding.Unicode);
Debug.Assert(_fontOptions != null);
_cmapInfo = new CMapInfo(ttDescriptor);
_descendantFont = new PdfCIDFont(document, FontDescriptor, fontData);
_descendantFont.CMapInfo = _cmapInfo;
// Create ToUnicode map
_toUnicode = new PdfToUnicodeMap(document, _cmapInfo);
document.Internals.AddObject(_toUnicode);
Elements.Add(Keys.ToUnicode, _toUnicode);
//BaseFont = ttDescriptor.FontName.Replace(" ", "");
BaseFont = ttDescriptor.FontName;
// CID fonts are always embedded
if (!BaseFont.Contains("+")) // HACK in PdfType0Font
BaseFont = CreateEmbeddedFontSubsetName(BaseFont);
FontDescriptor.FontName = BaseFont;
_descendantFont.BaseFont = BaseFont;
PdfArray descendantFonts = new PdfArray(document);
Owner._irefTable.Add(_descendantFont);
descendantFonts.Elements.Add(_descendantFont.Reference);
Elements[Keys.DescendantFonts] = descendantFonts;
}
XPdfFontOptions FontOptions
{
get { return _fontOptions; }
}
XPdfFontOptions _fontOptions;
public string BaseFont
{
get { return Elements.GetName(Keys.BaseFont); }
set { Elements.SetName(Keys.BaseFont, value); }
}
internal PdfCIDFont DescendantFont
{
get { return _descendantFont; }
}
readonly PdfCIDFont _descendantFont;
internal override void PrepareForSave()
{
base.PrepareForSave();
// Use GetGlyphIndices to create the widths array.
OpenTypeDescriptor descriptor = (OpenTypeDescriptor)FontDescriptor._descriptor;
StringBuilder w = new StringBuilder("[");
if (_cmapInfo != null)
{
int[] glyphIndices = _cmapInfo.GetGlyphIndices();
int count = glyphIndices.Length;
int[] glyphWidths = new int[count];
for (int idx = 0; idx < count; idx++)
glyphWidths[idx] = descriptor.GlyphIndexToPdfWidth(glyphIndices[idx]);
//TODO: optimize order of indices
for (int idx = 0; idx < count; idx++)
w.AppendFormat("{0}[{1}]", glyphIndices[idx], glyphWidths[idx]);
w.Append("]");
_descendantFont.Elements.SetValue(PdfCIDFont.Keys.W, new PdfLiteral(w.ToString()));
}
_descendantFont.PrepareForSave();
_toUnicode.PrepareForSave();
}
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public new sealed class Keys : PdfFont.Keys
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Font for a font dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Font")]
public new const string Type = "/Type";
/// <summary>
/// (Required) The type of font; must be Type0 for a Type 0 font.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string Subtype = "/Subtype";
/// <summary>
/// (Required) The PostScript name of the font. In principle, this is an arbitrary
/// name, since there is no font program associated directly with a Type 0 font
/// dictionary. The conventions described here ensure maximum compatibility
/// with existing Acrobat products.
/// If the descendant is a Type 0 CIDFont, this name should be the concatenation
/// of the CIDFont<6E>s BaseFont name, a hyphen, and the CMap name given in the
/// Encoding entry (or the CMapName entry in the CMap). If the descendant is a
/// Type 2 CIDFont, this name should be the same as the CIDFont<6E>s BaseFont name.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string BaseFont = "/BaseFont";
/// <summary>
/// (Required) The name of a predefined CMap, or a stream containing a CMap
/// that maps character codes to font numbers and CIDs. If the descendant is a
/// Type 2 CIDFont whose associated TrueType font program is not embedded
/// in the PDF file, the Encoding entry must be a predefined CMap name.
/// </summary>
[KeyInfo(KeyType.StreamOrName | KeyType.Required)]
public const string Encoding = "/Encoding";
/// <summary>
/// (Required) A one-element array specifying the CIDFont dictionary that is the
/// descendant of this Type 0 font.
/// </summary>
[KeyInfo(KeyType.Array | KeyType.Required)]
public const string DescendantFonts = "/DescendantFonts";
/// <summary>
/// ((Optional) A stream containing a CMap file that maps character codes to
/// Unicode values.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string ToUnicode = "/ToUnicode";
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static DictionaryMeta Meta
{
get
{
if (Keys._meta == null)
Keys._meta = CreateMeta(typeof(Keys));
return Keys._meta;
}
}
static DictionaryMeta _meta;
}
/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}

View File

@@ -0,0 +1,184 @@
#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
#if true_ // Not yet implemented-
using System;
using System.Collections;
using System.Text;
using System.IO;
using PdfSharp.Internal;
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Not implemented - just for illustration of the class hierarchy.
/// </summary>
internal sealed class PdfType1Font : PdfFont
{
public PdfType1Font(PdfDocument document)
: base(document)
{
Elements["\\Type"] = new PdfName("Font");
Elements["\\Subtype"] = new PdfName("Type1");
}
//public string BaseFont
//{
// get {return baseFont;}
// set {baseFont = value;}
//}
//string baseFont;
// internal override void AssignObjectID(ref int objectID)
// {
// SetObjectID(ref objectID);
// }
//
// internal override void WriteObject(Stream stream)
// {
// base.WriteObject(stream);
// StringBuilder pdf = new StringBuilder();
// pdf.AppendFormat("{0} 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n/BaseFont /Helvetica\n/Encoding /WinAnsiEncoding\n>>\nendobj\n", ObjectID);
// WriteString(stream, pdf.ToString());
// }
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public new sealed class Keys : PdfFont.Keys
{
/// <summary>
/// (Required) The type of PDF object that this dictionary describes;
/// must be Font for a font dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required, FixedValue = "Font")]
public new const string Type = "/Type";
/// <summary>
/// (Required) The type of font; must be Type1 for a Type 1 font.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string Subtype = "/Subtype";
/// <summary>
/// (Required in PDF 1.0; optional otherwise) The name by which this font is
/// referenced in the Font subdictionary of the current resource dictionary.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Optional)]
public const string Name = "/Name";
/// <summary>
/// (Required) The PostScript name of the font. For Type 1 fonts, this is usually
/// the value of the FontName entry in the font program; for more information.
/// The Post-Script name of the font can be used to find the font<6E>s definition in
/// the consumer application or its environment. It is also the name that is used when
/// printing to a PostScript output device.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Required)]
public new const string BaseFont = "/BaseFont";
/// <summary>
/// (Required except for the standard 14 fonts) The first character code defined
/// in the font<6E>s Widths array.
/// </summary>
[KeyInfo(KeyType.Integer)]
public const string FirstChar = "/FirstChar";
/// <summary>
/// (Required except for the standard 14 fonts) The last character code defined
/// in the font<6E>s Widths array.
/// </summary>
[KeyInfo(KeyType.Integer)]
public const string LastChar = "/LastChar";
/// <summary>
/// (Required except for the standard 14 fonts; indirect reference preferred)
/// An array of (LastChar - FirstChar + 1) widths, each element being the glyph width
/// for the character code that equals FirstChar plus the array index. For character
/// codes outside the range FirstChar to LastChar, the value of MissingWidth from the
/// FontDescriptor entry for this font is used. The glyph widths are measured in units
/// in which 1000 units corresponds to 1 unit in text space. These widths must be
/// consistent with the actual widths given in the font program.
/// </summary>
[KeyInfo(KeyType.Array, typeof(PdfArray))]
public const string Widths = "/Widths";
/// <summary>
/// (Required except for the standard 14 fonts; must be an indirect reference)
/// A font descriptor describing the font<6E>s metrics other than its glyph widths.
/// Note: For the standard 14 fonts, the entries FirstChar, LastChar, Widths, and
/// FontDescriptor must either all be present or all be absent. Ordinarily, they are
/// absent; specifying them enables a standard font to be overridden.
/// </summary>
[KeyInfo(KeyType.Dictionary | KeyType.MustBeIndirect, typeof(PdfFontDescriptor))]
public new const string FontDescriptor = "/FontDescriptor";
/// <summary>
/// (Optional) A specification of the font<6E>s character encoding if different from its
/// built-in encoding. The value of Encoding is either the name of a predefined
/// encoding (MacRomanEncoding, MacExpertEncoding, or WinAnsiEncoding, as described in
/// Appendix D) or an encoding dictionary that specifies differences from the font<6E>s
/// built-in encoding or from a specified predefined encoding.
/// </summary>
[KeyInfo(KeyType.Name | KeyType.Dictionary)]
public const string Encoding = "/Encoding";
/// <summary>
/// (Optional; PDF 1.2) A stream containing a CMap file that maps character
/// codes to Unicode values.
/// </summary>
[KeyInfo(KeyType.Stream | KeyType.Optional)]
public const string ToUnicode = "/ToUnicode";
/// <summary>
/// Gets the KeysMeta for these keys.
/// </summary>
internal static DictionaryMeta Meta
{
get
{
if (_meta == null)
_meta = CreateMeta(typeof(Keys));
return _meta;
}
}
static DictionaryMeta _meta;
}
/// <summary>
/// Gets the KeysMeta of this dictionary type.
/// </summary>
internal override DictionaryMeta Meta
{
get { return Keys.Meta; }
}
}
}
#endif

View File

@@ -0,0 +1,51 @@
#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
namespace PdfSharp.Pdf.Advanced
{
/// <summary>
/// Base class for all PDF external objects.
/// </summary>
public abstract class PdfXObject : PdfDictionary
{
/// <summary>
/// Initializes a new instance of the <see cref="PdfXObject"/> class.
/// </summary>
/// <param name="document">The document that owns the object.</param>
protected PdfXObject(PdfDocument document)
: base(document)
{ }
/// <summary>
/// Predefined keys of this dictionary.
/// </summary>
public class Keys : PdfStream.Keys
{ }
}
}