|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*++
Abstract:
This file contains the definition and implementation
for the XpsDocument class. This class acts as the
"root" of a Xps package and provides access to begin
reading and/or writing Xps packages.
--*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Packaging;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Documents;
using System.Windows.Media;
using System.Printing;
using System.Windows.Xps;
using System.Windows.Xps.Serialization;
using System.Windows.Markup;
using System.Threading;
using System.Xml;
using System.Security;
using MS.Internal;
using MS.Internal.Security;
using MS.Internal.IO.Packaging;
using MS.Internal.IO.Packaging.Extensions;
using Package = System.IO.Packaging.Package;
using PackUriHelper = System.IO.Packaging.PackUriHelper;
namespace System.Windows.Xps.Packaging
{
/// <summary>
/// This class implements the functionality to read and write Xps
/// packages.
/// </summary>
public class XpsDocument : XpsPartBase, INode, IDisposable
{
#region Constructors
/// <summary>
/// Constructs a XpsDocument instance to read from and/or write to
/// the supplied Metro package with the default compression options
/// and no support for rights management, resource policies, or
/// interleaving policies.
/// </summary>
/// <param name="package">
/// The target Metro package for this Xps package.
/// </param>
public
XpsDocument(
Package package
)
: this(package, CompressionOption.Maximum)
{
}
/// <summary>
/// Constructs a XpsDocument instance to read from and/or write to
/// the supplied Metro package with the supplied compression options
/// and rights management options.
/// </summary>
/// <param name="package">
/// The target Metro package for this Xps package.
/// </param>
/// <param name="compressionOption">
/// The compression option for this package.
/// </param>
public
XpsDocument(
Package package,
CompressionOption compressionOption
)
: this(package, compressionOption, null)
{
}
/// <summary>
/// Constructs a XpsDocument instance to read from and/or write to
/// the supplied Metro package with the supplied compression options
/// and rights management options.
/// </summary>
/// <param name="package">
/// The target Metro package for this Xps package.
/// </param>
/// <param name="compressionOption">
/// The compression option for this package.
/// </param>
/// <param name="path">
/// path to xps package
/// </param>
public
XpsDocument(
Package package,
CompressionOption compressionOption,
String path
)
: base(new XpsManager( package,
compressionOption
)
)
{
if( path != null )
{
this.Uri = new Uri(path, UriKind.RelativeOrAbsolute);
}
CurrentXpsManager.XpsDocument = this;
Initialize();
}
/// <summary>
/// Constructs a XpsDocument instance to read from and/or write to
/// the supplied Metro package with the default compression options
/// and no support for rights management, resource policies, or
/// interleaving policies.
/// </summary>
/// <param name="path">
/// path to package
/// </param>
/// <param name="packageAccess">
/// mode to the package can be accessed (i.e. Read, Write, Read/Write )
/// </param>
public
XpsDocument(
string path,
FileAccess packageAccess
): this( path, packageAccess, CompressionOption.Maximum)
{
}
/// <summary>
/// Constructs a XpsDocument instance to read from and/or write to
/// the supplied Metro package with the supplied compression options
/// and rights management options.
/// </summary>
/// <param name="path">
/// path to package
/// </param>
/// <param name="packageAccess">
/// mode to the package can be accessed (i.e. Read, Write, Read/Write )
/// </param>
/// <param name="compressionOption">
/// The compression option for this package.
/// </param>
public
XpsDocument(
string path,
FileAccess packageAccess,
CompressionOption compressionOption
)
: base(new XpsManager( path,
packageAccess,
compressionOption
)
)
{
ArgumentNullException.ThrowIfNull(path);
this.Uri = new Uri(path, UriKind.RelativeOrAbsolute);
//
//The URI has to be absolute
//If the path passed in is relative append it to the
//current working directory
//
if( !Uri.IsAbsoluteUri)
{
Uri = new Uri( new Uri(Directory.GetCurrentDirectory()+"/"), this.Uri );
}
CurrentXpsManager.XpsDocument = this;
Initialize();
}
#endregion Constructors
#region Public properties
/// <summary>
/// This property determines whether this instance is
/// a writer (i.e. It can write to the package).
/// </summary>
/// <value>A boolean representing write capabilities.</value>
public bool IsWriter
{
get
{
CheckDisposed();
return CurrentXpsManager.IsWriter;
}
}
/// <summary>
/// This property determines whether this instance is
/// a reader (i.e. It can read from the package).
/// </summary>
/// <value>A boolean representing read capability.</value>
public bool IsReader
{
get
{
CheckDisposed();
return CurrentXpsManager.IsReader;
}
}
/// <summary>
/// This method returns the root (starting part) of the Metro package as a DocumentSequenceReader.
/// </summary>
/// <returns>A DocumentSequenceReader representing the root.</returns>
/// <exception cref="SR.ReachPackaging_NotOpenForReading">Package not open for reading.</exception>
/// <exception cref="SR.ReachPackaging_InvalidStartingPart">Package starting part is not a valid root.</exception>
public
IXpsFixedDocumentSequenceReader
FixedDocumentSequenceReader
{
get
{
CheckDisposed();
XpsFixedDocumentSequenceReaderWriter value = null;
PackagePart startingPart = CurrentXpsManager.StartingPart;
if (IsReader && startingPart!= null)
{
value =new XpsFixedDocumentSequenceReaderWriter(CurrentXpsManager, null, startingPart);
}
return value;
}
}
/// <summary>
/// A list of reach sigantures associated with the pacakge
/// Given this list the user should be able to determine what
/// What parts have been signed and whether the signatures are valid
/// </summary>
/// <value>List of associated XpsSignatures</value>
public ReadOnlyCollection<XpsDigitalSignature> Signatures
{
get
{
CheckDisposed();
EnsureSignatures();
// Return a read-only collection referring to them
// This list maintains a reference to _signatures so its enumerator will adapt
// as _signatures is updated. Therefore, we need not regenerate it when _signatures
// is modified.
return _reachSignatureList ??= new ReadOnlyCollection<XpsDigitalSignature>(_reachSignatures);
}
}
/// <summary>
/// This propertert returns a class accesing the
/// Core Document Properties Part
/// Just accessing the property does not create the part.
/// If the part does not exist it will be created when one of
/// CoreDocumentProperties properties has be modified and commited.
/// </summary>
public
PackageProperties
CoreDocumentProperties
{
get
{
CheckDisposed();
return CurrentXpsManager.MetroPackage.PackageProperties;
}
}
/// <summary>
/// thumbnail image associated with this package
/// </summary>
public
XpsThumbnail
Thumbnail
{
get
{
CheckDisposed();
EnsureThumbnail();
return _thumbnail;
}
set
{
CheckDisposed();
_thumbnail = value;
}
}
/// <summary>
/// Does the document meet the policy for signing
/// </summary>
public
bool
IsSignable
{
get
{
CheckDisposed();
bool isSignable = true;
//
// List of parts containing XML that need to be checked for
// Version Extensiblitly
//
List<PackagePart> xmlPartList = new List<PackagePart>();
(FixedDocumentSequenceReader as XpsFixedDocumentSequenceReaderWriter).CollectXmlPartsAndDepenedents(xmlPartList);
foreach( PackagePart part in xmlPartList )
{
using (Stream stream = part.GetStream(FileMode.Open, FileAccess.Read))
{
//
// An empty stream contains not version extensibility thus is valid
// We do create empty parts for print tickets
//
if (stream.Length == 0)
continue;
try
{
if (StreamContainsVersionExtensiblity(stream))
{
isSignable = false;
break;
}
}
catch (XmlException)
{
isSignable = false;
break;
}
}
}
return isSignable;
}
}
#endregion Public properties
#region Public methods
/// <summary>
/// This method signs the supplied parts within the Metro package
/// using the supplied cerificate. If no certificate is supplied,
/// UI is displayed to select a certificate.
/// </summary>
/// <param name="certificate">
/// The certificate to use in signing
/// </param>
/// <param name="embedCertificate">
/// Flag indicating wheter the certificate should be inbeded in the package
/// </param>
/// <param name="restrictions">
/// Flags indicating what dependent parts should be excluded from the signing
/// </param>
/// <exception cref="ArgumentNullException">certificate is null.</exception>
public
XpsDigitalSignature
SignDigitally(
X509Certificate certificate,
bool embedCertificate,
XpsDigSigPartAlteringRestrictions restrictions
)
{
CheckDisposed();
return SignDigitally(
certificate,
embedCertificate,
restrictions,
null,
true
);
}
/// <summary>
/// This method signs the supplied parts within the Metro package
/// using the supplied cerificate. If no certificate is supplied,
/// UI is displayed to select a certificate.
/// </summary>
/// <param name="certificate">
/// The certificate to use in signing
/// </param>
/// <param name="embedCertificate">
/// Flag indicating wheter the certificate should be inbeded in the package
/// </param>
/// <param name="restrictions">
/// Flags indicating what dependent parts should be excluded from the signing
/// </param>
/// <param name="id">
/// Id to be assigned to the signature
/// </param>
/// <exception cref="ArgumentNullException">certificate is null.</exception>
public
XpsDigitalSignature
SignDigitally(
X509Certificate certificate,
bool embedCertificate,
XpsDigSigPartAlteringRestrictions restrictions,
Guid id
)
{
CheckDisposed();
return SignDigitally(
certificate,
embedCertificate,
restrictions,
XmlConvert.EncodeName(id.ToString()),
true
);
}
/// <summary>
/// This method signs the supplied parts within the Metro package
/// using the supplied cerificate. If no certificate is supplied,
/// UI is displayed to select a certificate.
/// </summary>
/// <param name="certificate">
/// The certificate to use in signing
/// </param>
/// <param name="embedCertificate">
/// Flag indicating wheter the certificate should be inbeded in the package
/// </param>
/// <param name="restrictions">
/// Flags indicating what dependent parts should be excluded from the signing
/// </param>
/// <param name="id">
/// Id to be assigned to the signature
/// </param>
/// <param name="testIsSignable">
/// Flag indicating if IsSignable should be called before signing
/// </param>
/// <exception cref="ArgumentNullException">certificate is null.</exception>
public
XpsDigitalSignature
SignDigitally(
X509Certificate certificate,
bool embedCertificate,
XpsDigSigPartAlteringRestrictions restrictions,
Guid id,
bool testIsSignable
)
{
CheckDisposed();
return SignDigitally(
certificate,
embedCertificate,
restrictions,
XmlConvert.EncodeName(id.ToString()),
testIsSignable
);
}
/// <summary>
/// Removes a Digital Signature
/// </summary>
/// <param name="signature">
/// The signature to be removed
/// </param>
/// <exception cref="ArgumentNullException">signature is null.</exception>
public
void
RemoveSignature(
XpsDigitalSignature signature
)
{
CheckDisposed();
ArgumentNullException.ThrowIfNull(signature);
if (null == signature.PackageSignature)
{
throw new NullReferenceException("signature.PackageSignature");
}
if (null == signature.PackageSignature.SignaturePart)
{
throw new NullReferenceException("signature.PackageSignature.SignaturePart");
}
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
PackageDigitalSignatureManager packageSignatures = new PackageDigitalSignatureManager(CurrentXpsManager.MetroPackage);
packageSignatures.RemoveSignature(signature.PackageSignature.SignaturePart.Uri );
_reachSignatures = null;
_reachSignatureList = null;
EnsureSignatures();
}
/// <summary>
/// This method adds a thumbnail to the current Xps package.
///
/// There can only be one thumbnail attached to the pakcage.
/// Calling this method when there
/// is already a starting part causes InvalidOperationException to be
/// thrown.
/// </summary>
/// <returns>Returns a XpsThumbnail instance.</returns>
public
XpsThumbnail
AddThumbnail(
XpsImageType imageType
)
{
CheckDisposed();
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
_thumbnail = CurrentXpsManager.AddThumbnail(imageType, this, Thumbnail);
Package metroPackage = CurrentXpsManager.MetroPackage;
metroPackage.CreateRelationship( _thumbnail.Uri,
TargetMode.Internal,
XpsS0Markup.ThumbnailRelationshipName
);
return _thumbnail;
}
/// <summary>
/// This method adds a document sequence to the current Xps package as
/// the root (starting part) of the package and returns an instance of
/// a writer interface for writing to the document sequence.
///
/// There can only be one starting part. Calling this method when there
/// is already a starting part causes InvalidOperationException to be
/// thrown.
/// </summary>
/// <returns>Returns a IXpsFixedDocumentSequenceWriter instance.</returns>
/// <exception cref="SR.ReachPackaging_AlreadyHasRootSequenceOrDocument">Package already has a root DocumentSequence.</exception>
public
IXpsFixedDocumentSequenceWriter
AddFixedDocumentSequence(
)
{
CheckDisposed();
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
if (_isInDocumentStage)
{
throw new XpsPackagingException(SR.ReachPackaging_AlreadyHasRootSequenceOrDocument);
}
if ( !CurrentXpsManager.Streaming && null != CurrentXpsManager.StartingPart)
{
throw new XpsPackagingException(SR.ReachPackaging_AlreadyHasRootSequenceOrDocument);
}
//
// Create the unique metro part in the package
//
PackagePart metroPart = CurrentXpsManager.GenerateUniquePart(XpsS0Markup.DocumentSequenceContentType);
//
// Create reader/writer and save a reference to it.
//
XpsFixedDocumentSequenceReaderWriter ds = new XpsFixedDocumentSequenceReaderWriter(CurrentXpsManager, this, metroPart);
CurrentXpsManager.StartingPart = ((INode)ds).GetPart();
return ds;
}
/// <summary>
/// This method returns the root (starting part) of the Metro package.
/// The return value can either be an instance of a document sequence or
/// a fixed document.
/// </summary>
/// <returns>A XpsPartBase representing the root.</returns>
/// <remarks>Method will be internal until reading/de-serialization is implemented.</remarks>
/// <exception cref="SR.ReachPackaging_PackageUriNull">XpsPakage Uri is null. Use XpsDocument constructor that takes Uri parameter.</exception>
/// <exception cref="SR.ReachPackaging_InvalidStartingPart">Package starting part is not a valid root.</exception>
/// <exception cref="SR.ReachPackaging_NotAFixedDocumentSequence">Part Uri does not corresepond to a Fixed Document Sequence.</exception>
public
FixedDocumentSequence
GetFixedDocumentSequence(
)
{
CheckDisposed();
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
if (!IsReader)
{
throw new XpsPackagingException(SR.ReachPackaging_NotOpenForReading);
}
if (null == Uri)
{
throw new XpsPackagingException(SR.ReachPackaging_PackageUriNull);
}
if (CurrentXpsManager.StartingPart == null)
{
return null;
}
ContentType startPartType = CurrentXpsManager.StartingPart.ValidatedContentType();
if (!startPartType.AreTypeAndSubTypeEqual(XpsS0Markup.DocumentSequenceContentType))
{
throw new XpsPackagingException(SR.ReachPackaging_InvalidStartingPart);
}
ParserContext parserContext = new ParserContext();
parserContext.BaseUri = PackUriHelper.Create(Uri, CurrentXpsManager.StartingPart.Uri);
object fixedObject = XamlReader.Load(CurrentXpsManager.StartingPart.GetStream(), parserContext, useRestrictiveXamlReader: true);
if (!(fixedObject is FixedDocumentSequence) )
{
throw new XpsPackagingException(SR.ReachPackaging_NotAFixedDocumentSequence);
}
return fixedObject as FixedDocumentSequence;
}
/// <summary>
/// This method commits the changes of the package and closes it.
/// Further changes after a commit will cause an exception to be
/// thrown.
/// </summary>
internal
override
void
CommitInternal(
)
{
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
base.CommitInternal();
}
/// <summary>
/// Writes the close elements for both the starting part and the package
/// </summary>
public
void
Close(
)
{
Dispose(true);
}
#endregion Public methods
#region protected methods
///<Summary>
/// Handles releasing XpsDocuments resources
///</Summary>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_thumbnail = null;
_reachSignatures = null;
_reachSignatureList = null;
_opcPackage = null;
CurrentXpsManager.Close();
CommitInternal();
}
GC.SuppressFinalize(this);
_disposed = true;
}
#endregion
#region Private methods
/// <summary>
/// This method is a helper method used when constructing the
/// current instance.
/// </summary>
private
void
Initialize(
)
{
_isInDocumentStage = false;
_opcPackage = null;
}
private
void
EnsureThumbnail()
{
if( _thumbnail == null )
{
_thumbnail = CurrentXpsManager.EnsureThumbnail(this, null );
}
}
private
void
EnsureSignatures()
{
//
// if _reachSignaturs is not null we have already initialized this
//
if( null != _reachSignatures )
{
return;
}
_reachSignatures = new Collection<XpsDigitalSignature>();
PackageDigitalSignatureManager packageSignatures = new PackageDigitalSignatureManager(CurrentXpsManager.MetroPackage);
foreach( PackageDigitalSignature packSignature in packageSignatures.Signatures )
{
XpsDigitalSignature reachSignature = new XpsDigitalSignature( packSignature, this );
//
// Only add signatures that meet the policy for
// signed Document Sequences
//
if( reachSignature.SignedDocumentSequence != null )
{
_reachSignatures.Add( reachSignature );
}
}
}
internal
void
CollectSelfAndDependents(
Dictionary<Uri,Uri> dependentList,
List<PackageRelationshipSelector> selectorList,
XpsDigSigPartAlteringRestrictions restrictions
)
{
(FixedDocumentSequenceReader as XpsFixedDocumentSequenceReaderWriter).CollectSelfAndDependents(
dependentList,
selectorList,
restrictions);
//
// Add thumbnail
//
EnsureThumbnail();
if( _thumbnail != null )
{
dependentList[_thumbnail.Uri] = _thumbnail.Uri;
}
//
// Sign Starting part relationship
//
selectorList.Add( new PackageRelationshipSelector(
MS.Internal.IO.Packaging.PackUriHelper.PackageRootUri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.ReachPackageStartingPartRelationshipType
)
);
//
// Add thumnail relationship
//
selectorList.Add(new PackageRelationshipSelector(
MS.Internal.IO.Packaging.PackUriHelper.PackageRootUri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.ThumbnailRelationshipName
)
);
//
// Sign CoreMetadata type if the restriction flag is set
//
if( (restrictions & XpsDigSigPartAlteringRestrictions.CoreMetadata)!= 0 )
{
//We need to flush the package because the core properties are not written out
//until the package is flushed
CurrentXpsManager.MetroPackage.Flush();
selectorList.Add( new PackageRelationshipSelector(
MS.Internal.IO.Packaging.PackUriHelper.PackageRootUri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.CorePropertiesRelationshipType
)
);
}
//
// Add the Signiture Origin based on the restrictions
//
CurrentXpsManager.CollectSignitureOriginForSigning(selectorList, restrictions );
//
// Add the properties based on the restrictions
//
CurrentXpsManager.CollectPropertiesForSigning(dependentList, restrictions );
}
private
XpsDigitalSignature
AddSignature(PackageDigitalSignature packSignature)
{
XpsDigitalSignature reachSignature =
new XpsDigitalSignature( packSignature, this );
_reachSignatures.Add( reachSignature );
return reachSignature;
}
private
bool
StreamContainsVersionExtensiblity( Stream stream )
{
XmlReader xmlReader = new XmlTextReader( stream );
bool containsVersionExtensiblity = false;
while( xmlReader.Read() );
if (xmlReader.NameTable.Get(XpsS0Markup.VersionExtensiblityNamespace) != null)
{
containsVersionExtensiblity = true;
}
return containsVersionExtensiblity;
}
private
XpsDigitalSignature
SignDigitally(
X509Certificate certificate,
bool embedCertificate,
XpsDigSigPartAlteringRestrictions restrictions,
String signatureId,
bool testIsSignable
)
{
ArgumentNullException.ThrowIfNull(certificate);
if( CurrentXpsManager == null )
{
throw new InvalidOperationException(SR.ReachPackaging_DocumentWasClosed);
}
if( testIsSignable && !IsSignable )
{
throw new InvalidOperationException(SR.ReachPackaging_SigningDoesNotMeetPolicy);
}
EnsureSignatures();
//
// List of RelationshipSelectors that need to be signed
//
List<PackageRelationshipSelector> selectorList =
new List<PackageRelationshipSelector>();
//
// This is being used as a Set class so the second Uri Value is irrelevent
//
Dictionary<Uri,Uri> dependentList = new Dictionary<Uri,Uri> ();
CollectSelfAndDependents( dependentList, selectorList, restrictions );
PackageDigitalSignature packSignature =
CurrentXpsManager.Sign(dependentList.Keys,
certificate,
embedCertificate,
selectorList,
signatureId
);
return AddSignature(packSignature);
}
internal
static
XpsDocument
CreateXpsDocument(
Stream dataStream
)
{
// In .NET Core 3.0 System.IO.Compression's ZipArchive does not allow creation of ZipArchiveEntries when
// a prior ZipArchiveEntry is still open. XPS Serialization requires this as part of its implementation.
// To get around this, XPS creation should occur in with FileAccess.ReadWrite if the underlying stream
// supports it. This allows multiple ZipArchiveEntries to be open concurrently.
Package package = Package.Open(dataStream,
FileMode.CreateNew,
(dataStream.CanRead) ? FileAccess.ReadWrite : FileAccess.Write);
XpsDocument document = new XpsDocument(package);
document.OpcPackage = package;
return document;
}
internal
void
DisposeXpsDocument(
)
{
if(_opcPackage != null)
{
_opcPackage.Close();
}
}
internal
Package
OpcPackage
{
set
{
_opcPackage = value;
}
}
/// <summary>
/// This is a pass thru to allow system printing access to method of the
/// same name in WindowsBase
/// </summary>
internal static void SaveWithUI(IntPtr parent, Uri source, Uri target)
{
AttachmentService.SaveWithUI(parent, source, target );
}
#endregion Private methods
#region Private data
//
// This variable signals that we have created the root
// document sequence or fixed document. Once this flag
// is set, no more changes are allowed to either the
// PrintTicket or XpsProperties.
//
private bool _isInDocumentStage;
private Collection<XpsDigitalSignature> _reachSignatures;
private ReadOnlyCollection<XpsDigitalSignature> _reachSignatureList;
private XpsThumbnail _thumbnail;
private Package _opcPackage;
bool _disposed = false;
#endregion Private data
#region IDisposable implementation
void
IDisposable.Dispose(
)
{
Close();
}
#endregion IDisposable implementation
private void CheckDisposed()
{
ObjectDisposedException.ThrowIf(_disposed, typeof(XpsDocument));
}
#region INode implementation
void
INode.Flush(
)
{
if (CurrentXpsManager.Streaming)
{
//CurrentXpsManager.MetroPackage.FlushPackageRelationships();
}
}
void
INode.CommitInternal(
)
{
Close();
}
PackagePart
INode.GetPart(
)
{
return null;
}
#endregion INode implementation
/// <summary>
/// Creates and returns the appropriate <c>PackageSerializationManager</c>.
/// </summary>
/// <returns><c>PackageSerializationManager</c></returns>
internal
PackageSerializationManager
CreateSerializationManager(
bool bBatchMode
)
{
PackageSerializationManager serializationManager = null;
XpsPackagingPolicy packagingPolicy = new XpsPackagingPolicy(this);
if (packagingPolicy != null)
{
serializationManager = new XpsSerializationManager(packagingPolicy, bBatchMode);
}
return serializationManager;
}
/// <summary>
/// Creates and returns the appropriate <c>MetroAsyncSerializationManager</c>.
/// </summary>
/// <returns><c>AsyncPackageSerializationManager</c></returns>
internal
PackageSerializationManager
CreateAsyncSerializationManager(
bool bBatchMode
)
{
PackageSerializationManager serializationManager = null;
XpsPackagingPolicy packagingPolicy = new XpsPackagingPolicy(this);
serializationManager = new XpsSerializationManagerAsync(packagingPolicy, bBatchMode);
return serializationManager;
}
/// <summary>
/// Dispose a serializaiton manager
/// </summary>
internal
void
DisposeSerializationManager(
)
{
}
/// <summary>
/// Creates an <c>XpsDocumentWriter</c> and initiates it against the <c>XpsDocument</c>
/// </summary>
/// <param name="xpsDocument">to initialize against</param>
/// <returns><c>XPSDocumentWriter</c></returns>
/// <remarks>XpsDocumentWriter checks XPS implementation limits as defined in Section 11.2 of XPS Specification and Reference Guide.
/// When violations are detected, XML comments will be inserted in the markup generated. Here are some examples:
/// "XPSLimit:FloatRange" for value outside of suggested range.
/// "XPSLimit:PointCount" for too many points in a geometry.
/// "XPSLimit:GradientStopCount" for too many stops in gradient stop collection
/// "XPSLimit:ResourceCount" for too many resources in a resource dictionary
/// "XPSLimit:ElementCount" for too many elements in a FixedPage
/// </remarks>
public
static
System.
Windows.
Xps.
XpsDocumentWriter
CreateXpsDocumentWriter(
XpsDocument xpsDocument
)
{
XpsDocumentWriter writer = new XpsDocumentWriter(xpsDocument);
return writer;
}
#region Public Events
#endregion Public Events
}
}
|