|
// 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 for IXpsFixedDocumentReader
and IXpsFixedDocumentWriter interfaces as well as definition
and implementation of XpsFixedDocumentReaderWriter. These
interfaces and class are used for writing fixed document
parts to a Xps package.
--*/
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Packaging;
using System.Xml;
using System.Printing;
using MS.Internal.IO.Packaging.Extensions;
using PackageRelationship = System.IO.Packaging.PackageRelationship;
using PackUriHelper = System.IO.Packaging.PackUriHelper;
namespace System.Windows.Xps.Packaging
{
#region IXpsFixedDocumentReader interface definition
/// <summary>
/// Interface for reading fixed document parts from the Xps package.
/// </summary>
/// <remarks>Interface will be internal until reading/de-serialization is implemented.</remarks>
public interface IXpsFixedDocumentReader:
IDocumentStructureProvider
{
#region Public methods
/// <summary>
/// This method retrieves a fixed page part from a Xps
/// package using the given URI.
/// </summary>
/// <param name="pageSource">
/// The URI of the fixed page to retrieve.
/// </param>
/// <returns>
/// Returns an interface to an IXpsFixedPageReader to read
/// the requested fixed page.
/// </returns>
IXpsFixedPageReader
GetFixedPage(
Uri pageSource
);
#endregion Public methods
#region Public properties
/// <summary>
/// Gets the PrintTicket associated with this fixed document.
/// </summary>
/// <value>Value can be a PrintTicket or null.</value>
/// <exception cref="SR.ReachPackaging_PrintTicketAlreadyCommitted">PrintTicket has already been committed.</exception>
/// <exception cref="SR.ReachPackaging_NotAPrintTicket">Property is not a valid PrintTicket instance.</exception>
PrintTicket PrintTicket { get; }
/// <summary>
/// Gets the URI assigned to this fixed document part.
/// </summary>
/// <value>Value is a URI for the Metro part.</value>
Uri Uri { get; }
/// <summary>
/// Gets a collection of all fixed pages that are contained within
/// this fixed document.
/// </summary>
/// <value>
/// Value is a Collection containing IXpsFixedPageReader interfaces.
/// </value>
ReadOnlyCollection<IXpsFixedPageReader> FixedPages { get; }
/// <summary>
/// 0 based document number in the document sequence
/// </summary>
int DocumentNumber{ get; }
/// <summary>
/// A list of signature definitions associated with the document
/// </summary>
ICollection<XpsSignatureDefinition>
SignatureDefinitions{ get; }
/// <summary>
/// thumbnail image associated with this document
/// </summary>
XpsThumbnail
Thumbnail{ get; }
/// <summary>
/// Document Structure associated with this document
/// </summary>
XpsStructure
DocumentStructure{ get; }
#endregion Public properties
/// <summary>
/// Adds the passed Signature Definiton to the cached
/// Signature Definition list
/// Will not be written until FlushSignatureDefinition
/// is called
/// </summary>
/// <param name="signatureDefinition">
/// the Signature Definition to be added
/// </param>
void
AddSignatureDefinition(
XpsSignatureDefinition signatureDefinition
);
/// <summary>
/// This method removes a signature definitions associated with
/// the FixedDocument
/// </summary>
/// <param name="signatureDefinition">
/// Signature Definition to remove
/// </param>
void
RemoveSignatureDefinition(XpsSignatureDefinition signatureDefinition);
/// <summary>
/// Writes out all modifications to Signature
/// Definitions as well as new Signature Definitions
/// </summary>
void
CommitSignatureDefinition();
}
#endregion IXpsFixedDocumentReader interface definition
#region IXpsFixedDocumentWriter interface definition
/// <summary>
/// Interface for writing fixed document parts to the xps package.
/// </summary>
public interface IXpsFixedDocumentWriter:
IDocumentStructureProvider
{
#region Public methods
/// <summary>
/// This method adds a fixed page part to the Xps package
/// and associates it with the current fixed document.
/// </summary>
/// <returns>
/// Returns an interface to the newly created fixed page.
/// </returns>
/// <exception cref="ObjectDisposedException">The FixedDocument has already been disposed</exception>
/// <exception cref="SR.ReachPackaging_PanelOrSequenceAlreadyOpen">FixedPage is not completed.</exception>
IXpsFixedPageWriter
AddFixedPage(
);
/// <summary>
/// This method adds a thumbnail to the current DocumentSequence.
///
/// There can only be one thumbnail attached to the DocumentSequence.
/// Calling this method when there
/// is already a starting part causes InvalidOperationException to be
/// thrown.
/// </summary>
/// <returns>Returns a XpsThumbnail instance.</returns>
XpsThumbnail
AddThumbnail(
XpsImageType imageType
);
/// <summary>
/// This method commits any changes not already committed for this
/// fixed document.
///
/// </summary>
void
Commit(
);
#endregion Public methods
#region Public properties
/// <summary>
/// Sets the PrintTicket associated with this fixed document.
/// </summary>
/// <value>
/// The value must be a valid PrintTicket instance.
///
/// Note: The PrintTicket can only be assigned to prior to if being
/// committed to the package. The commit happens when a valid PrintTicket
/// is set and a subsequent flush on the document occurs.
/// </value>
/// <exception cref="SR.ReachPackaging_PrintTicketAlreadyCommitted">PrintTicket has already been committed.</exception>
/// <exception cref="SR.ReachPackaging_NotAPrintTicket">Property is not a valid PrintTicket instance.</exception>
PrintTicket PrintTicket { set; }
/// <summary>
/// Gets the URI assigned to this fixed document part.
/// </summary>
/// <value>Value is a URI for the Metro part.</value>
Uri Uri { get; }
/// <summary>
/// 0 based document number in the document sequence
/// </summary>
int DocumentNumber{ get; }
#endregion Public properties
}
#endregion IXpsFixedDocumentWriter interface definition
/// <summary>
/// This class implements the reading and writing functionality for
/// a fixed document within a Xps package.
/// </summary>
internal sealed class XpsFixedDocumentReaderWriter : XpsPartBase,
IXpsFixedDocumentReader,
IXpsFixedDocumentWriter,
INode,
IDisposable
{
#region Constructors
/// <summary>
/// Internal constructor for the XpsFixedDocumentReaderWriter class.
/// This class is created internally so we can keep the Xps hierarchy
/// completely under control when using these APIs.
/// </summary>
/// <param name="xpsManager">
/// The XpsManager for the current Xps package.
/// </param>
/// <param name="parent">
/// The parent node of this fixed document.
/// </param>
/// <param name="part">
/// The internal Metro part that represents this fixed document.
/// </param>
/// <param name="documentNumber">
/// The 0 base document number in the document sequence
/// </param>
/// <exception cref="ArgumentNullException">part is null.</exception>
internal
XpsFixedDocumentReaderWriter(
XpsManager xpsManager,
INode parent,
PackagePart part,
int documentNumber
)
: base(xpsManager)
{
ArgumentNullException.ThrowIfNull(part);
this.Uri = part.Uri;
_metroPart = part;
_partEditor = new XmlPartEditor(_metroPart);
_pageCache = new List<IXpsFixedPageReader>();
_pagesWritten = 0;
_parentNode = parent;
_hasParsedPages = false;
_documentNumber = documentNumber;
}
#endregion Constructors
#region Public properties
/// <summary>
/// Gets or sets the PrintTicket to be stored with this fixed document.
///
/// NOTE: The PrintTicket can only be assigned to prior to if being
/// committed to the package. The commit happens when a valid PrintTicket
/// is set and a subsequent flush on the document occurs.
/// </summary>
/// <value>Value can be a PrintTicket or null.</value>
/// <exception cref="SR.ReachPackaging_PrintTicketAlreadyCommitted">PrintTicket has already been committed.</exception>
/// <exception cref="SR.ReachPackaging_NotAPrintTicket">Property is not a valid PrintTicket instance.</exception>
public PrintTicket PrintTicket
{
get
{
if( _printTicket == null )
{
_printTicket = CurrentXpsManager.EnsurePrintTicket( Uri );
}
return _printTicket;
}
set
{
if(value != null)
{
if (_isPrintTicketCommitted)
{
throw new XpsPackagingException(SR.ReachPackaging_PrintTicketAlreadyCommitted);
}
if (!value.GetType().Equals(typeof(PrintTicket)))
{
throw new XpsPackagingException(SR.ReachPackaging_NotAPrintTicket);
}
_printTicket = value.Clone();
}
else
{
_printTicket = null;
}
}
}
/// <summary>
/// Gets a collection of all fixed pages that are contained within
/// this fixed document.
/// </summary>
/// <value>
/// Value is a Collection containing IXpsFixedPageReader interfaces.
/// </value>
/// <remarks>
/// This is only internal until it is implemented.
/// </remarks>
public ReadOnlyCollection<IXpsFixedPageReader> FixedPages
{
get
{
UpdatePageCache();
return new ReadOnlyCollection<IXpsFixedPageReader>(_pageCache );
}
}
/// <summary>
/// A list of signature definitions associated with the document
/// </summary>
public
ICollection<XpsSignatureDefinition>
SignatureDefinitions
{
get
{
EnsureSignatureDefinitions();
return _signatureDefinitions;
}
}
/// <summary>
/// 0 based document number in the document sequence
/// </summary>
public int DocumentNumber
{
get
{
return _documentNumber;
}
}
public
XpsThumbnail
Thumbnail
{
get
{
EnsureThumbnail();
return _thumbnail;
}
}
public
XpsStructure
DocumentStructure
{
get
{
EnsureDocumentStructure();
return _documentStructure;
}
}
#endregion Public properties
#region Public methods
/// <summary>
/// This method adds a fixed page part to the Xps package
/// and associates it with the current fixed document.
/// </summary>
/// <returns>
/// Returns an interface to the newly created fixed page.
/// </returns>
/// <exception cref="ObjectDisposedException">The FixedDocument has already been disposed</exception>
/// <exception cref="SR.ReachPackaging_PanelOrSequenceAlreadyOpen">FixedPage is not completed.</exception>
public
IXpsFixedPageWriter
AddFixedPage(
)
{
ObjectDisposedException.ThrowIf(_metroPart is null || CurrentXpsManager.MetroPackage is null, typeof(XpsFixedDocumentReaderWriter));
//
// Only one page can be created/written at a time.
//
if (null != _currentPage)
{
throw new XpsPackagingException(SR.ReachPackaging_PanelOrSequenceAlreadyOpen);
}
_linkTargetStream = new List<String>();
//
// Create the part and writer
//
PackagePart metroPart = this.CurrentXpsManager.GenerateUniquePart(XpsS0Markup.FixedPageContentType);
XpsFixedPageReaderWriter fixedPage = new XpsFixedPageReaderWriter(CurrentXpsManager, this, metroPart, _linkTargetStream, _pagesWritten + 1);
//
// Make the new page the current page
//
_currentPage = fixedPage;
//Here we used to add the fixed page to _pageCache, but _pageCache is never accessed if this object was created as an IXpsFixedDocumentWriter.
//So instead keep a separate pagesWritten count and forget about the cache when using this method.
_pagesWritten++;
return fixedPage;
}
/// <summary>
/// This method adds a thumbnail to the current DocumentSequence.
///
/// There can only be one thumbnail attached to the DocumentSequence.
/// 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
)
{
_thumbnail = CurrentXpsManager.AddThumbnail( imageType, this, Thumbnail );
_metroPart.CreateRelationship( _thumbnail.Uri,
TargetMode.Internal,
XpsS0Markup.ThumbnailRelationshipName
);
return _thumbnail;
}
/// <summary>
/// </summary>
public
XpsStructure
AddDocumentStructure(
)
{
if (this.DocumentStructure != null)
{
// Document structure already available for this FixedDocument
throw new XpsPackagingException(SR.ReachPackaging_MoreThanOneDocStructure);
}
Uri pageUri = this.CurrentXpsManager.CreateStructureUri();
//
// Create the part and writer
//
PackagePart metroPart = this.CurrentXpsManager.GeneratePart(
XpsS0Markup.DocumentStructureContentType,
pageUri);
_documentStructure = new XpsStructure(CurrentXpsManager, this, metroPart);
//
// Create the relationship between the document and the document-structure
// Not in INode.Flush because IXpsFixedDocumentReader has no commit.
//
string structurePath = XpsManager.MakeRelativePath(this.Uri, _documentStructure.Uri);
_metroPart.CreateRelationship(new Uri(structurePath, UriKind.Relative),
TargetMode.Internal,
XpsS0Markup.StructureRelationshipName
);
return _documentStructure;
}
/// <summary>
/// This method adds a relationship for this part that
/// targets the specified Uri and is based on the specified
/// content type.
/// </summary>
/// <param name="targetUri">
/// Uri target for relationship.
/// </param>
/// <param name="relationshipName">
/// Relationship type to add.
/// </param>
public
void
AddRelationship(
Uri targetUri,
string relationshipName
)
{
//
// We can not read from the file to do validation
// when streaming
//
if( !CurrentXpsManager.Streaming )
{
foreach (PackageRelationship rel in _metroPart.GetRelationships())
{
if (rel.TargetUri.Equals(targetUri))
{
//
// Relationship already exists
//
return;
}
}
}
//
// Add the relationship using a relative path to this page.
//
string relativePath = XpsManager.MakeRelativePath(this.Uri, targetUri);
_metroPart.CreateRelationship(new Uri(relativePath, UriKind.Relative),
TargetMode.Internal,
relationshipName);
}
/// <summary>
/// This method retrieves a fixed page part from a Xps
/// package using the given URI.
/// </summary>
/// <param name="pageUri">
/// The URI of the fixed page to retrieve.
/// </param>
/// <returns>
/// Returns an interface to an IXpsFixedPageReader to read
/// the requested fixed page.
/// </returns>
public
IXpsFixedPageReader
GetFixedPage(
Uri pageUri
)
{
UpdatePageCache();
IXpsFixedPageReader pageReader = null;
foreach (IXpsFixedPageReader reader in _pageCache )
{
if( reader.Uri == pageUri )
{
pageReader = reader;
}
}
return pageReader;
}
public
void
AddSignatureDefinition(
XpsSignatureDefinition signatureDefinition
)
{
EnsureSignatureDefinitions();
_signatureDefinitions.Add( signatureDefinition );
_sigCollectionDirty = true;
}
public
void
CommitSignatureDefinition()
{
bool isDirty = false;
//
// if the collection is dirty not point in testing
// each signature.
//
if( !_sigCollectionDirty )
{
foreach( XpsSignatureDefinition sigDef in _signatureDefinitions )
{
if( sigDef.HasBeenModified )
{
isDirty = true;
break;
}
}
}
if( isDirty || _sigCollectionDirty )
{
WriteSignatureDefinitions();
}
}
/// <summary>
/// This method removes a signature definitions associated with
/// the FixedDocument
/// </summary>
/// <param name="signatureDefinition">
/// Signature Definition to remove
/// </param>
public
void
RemoveSignatureDefinition(XpsSignatureDefinition signatureDefinition)
{
EnsureSignatureDefinitions();
_signatureDefinitions.Remove( signatureDefinition );
_sigCollectionDirty = true;
}
/// <summary>
/// This method commits any changes not already committed for this
/// fixed document.
///
/// NOTE: This commits changes to all child object under this
/// branch of the tree. No further changes will be allowed.
/// </summary>
public
void
Commit(
)
{
CommitInternal();
}
/// <summary>
/// This method closes streams and frees memory for this
/// fixed document.
/// </summary>
internal
override
void
CommitInternal(
)
{
CommitPrintTicket();
if (null != _partEditor)
{
if (null != _partEditor.XmlWriter)
{
if(_partEditor.DoesWriteStartEndTags)
{
if(_partEditor.IsStartElementWritten)
{
_partEditor.XmlWriter.WriteEndElement();
_partEditor.XmlWriter.WriteEndDocument();
}
}
}
((INode)this).Flush();
_partEditor.Close();
_partEditor = null;
_metroPart = null;
_parentNode = null;
_thumbnail = null;
_pageCache = null;
_pagesWritten = 0;
_hasParsedPages = false;
}
base.CommitInternal();
}
/// <summary>
/// Adds itself and and its reationship if it exists
/// Adds dependent part Uris to the passed list following the passed restrictions
/// dependents include pages, annotaions, properties, and signatures
/// </summary>
internal
void
CollectSelfAndDependents(
Dictionary<Uri,Uri> dependentList,
List<PackageRelationshipSelector> selectorList,
XpsDigSigPartAlteringRestrictions restrictions
)
{
//
// Add this document
//
dependentList[Uri] = Uri;
//
// Add Signature Definition if it exists
//
PackagePart signatureDefinitionPart =
CurrentXpsManager.GetSignatureDefinitionPart(Uri);
//
// Add Signature Definitions
//
selectorList.Add( new PackageRelationshipSelector(
Uri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.SignatureDefinitionRelationshipName
)
);
if( signatureDefinitionPart != null )
{
dependentList[signatureDefinitionPart.Uri] = signatureDefinitionPart.Uri;
}
//
// Add Restricted Font relationship
//
selectorList.Add( new PackageRelationshipSelector(
Uri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.RestrictedFontRelationshipType
)
);
//
// Add Document Structure relationship
//
selectorList.Add( new PackageRelationshipSelector(
Uri,
PackageRelationshipSelectorType.Type,
XpsS0Markup.StructureRelationshipName
)
);
//
// Add this documents dependants
//
CollectDependents( dependentList, selectorList, restrictions);
}
internal
void
CollectXmlPartsAndDepenedents(
List<PackagePart> xmlPartList
)
{
//
// Add my self to be tested for V&E Markup
//
xmlPartList.Add(_metroPart);
UpdatePageCache();
//
// Add all pages
//
foreach (IXpsFixedPageReader reader in _pageCache)
{
(reader as XpsFixedPageReaderWriter).CollectXmlPartsAndDepenedents(xmlPartList);
}
//
// Add DocumentStructure
//
EnsureDocumentStructure();
if (_documentStructure != null)
{
//
// Add my DocumentStructure to be tested for V&E Markup
//
xmlPartList.Add((_documentStructure as INode).GetPart());
}
//
// Add Signature Definition if it exists
//
PackagePart signatureDefinitionPart =
CurrentXpsManager.GetSignatureDefinitionPart(Uri);
if (signatureDefinitionPart != null)
{
//
// Add my signatureDefinitionPart to be tested for V&E Markup
//
xmlPartList.Add(signatureDefinitionPart);
}
}
/// <summary>
/// Adds dependent part Uris to the passed list
/// </summary>
internal
void
CollectDependents(
Dictionary<Uri,Uri> dependents,
List<PackageRelationshipSelector> selectorList,
XpsDigSigPartAlteringRestrictions restrictions
)
{
UpdatePageCache();
//
// Add all pages
//
foreach( IXpsFixedPageReader reader in _pageCache)
{
(reader as XpsFixedPageReaderWriter).
CollectSelfAndDependents(
dependents,
selectorList,
restrictions
);
}
//
// Add DocumentStructure
//
EnsureDocumentStructure();
if( _documentStructure != null )
{
dependents[_documentStructure.Uri] = _documentStructure.Uri;
}
}
#endregion Public methods
#region Private methods
private
void
AddPageToDocument(
Uri partUri,
IList<String> linkTargetStream
)
{
_partEditor.PrepareXmlWriter(XpsS0Markup.FixedDocument, XpsS0Markup.FixedDocumentNamespace);
XmlTextWriter xmlWriter = _partEditor.XmlWriter;
//
// Write <PageContent Target="partUri"/>
//
String relativePath = XpsManager.MakeRelativePath(Uri, partUri);
xmlWriter.WriteStartElement(XpsS0Markup.PageContent);
xmlWriter.WriteAttributeString(XmlTags.Source, relativePath);
//
// Write out link targets if necessary
//
if (linkTargetStream.Count != 0)
{
xmlWriter.WriteRaw ("<PageContent.LinkTargets>");
foreach (String nameElement in linkTargetStream)
{
xmlWriter.WriteRaw (String.Format(
System.Globalization.CultureInfo.InvariantCulture,
"<LinkTarget Name=\"{0}\" />",
nameElement)
);
}
xmlWriter.WriteRaw ("</PageContent.LinkTargets>");
}
xmlWriter.WriteEndElement();
}
/// <summary>
/// This method writes the PrintTicket associated with
/// this fixed document to the Metro package.
/// </summary>
private
void
CommitPrintTicket(
)
{
//
// Flush the PrintTicket if needed
//
if (!_isPrintTicketCommitted )
{
if(null != _printTicket)
{
CurrentXpsManager.WritePrintTicket(this,_metroPart, _printTicket);
}
else
{
CurrentXpsManager.WriteEmptyPrintTicket(this, _metroPart);
}
_isPrintTicketCommitted = true;
}
}
/// <summary>
/// CurrentPageCommitted signals that our current page
/// is complete and we can write out any associated link
/// targets and end the PageContent element.
/// </summary>
internal
void
CurrentPageCommitted()
{
if( _currentPage != null )
{
//Write out the fixed page tag
AddPageToDocument(_currentPage.Uri, _linkTargetStream);
_currentPage = null;
}
}
/// <summary>
/// Test if the page cache has been initialized and
/// updates it if necessary
/// </summary>
private
void
UpdatePageCache()
{
if( !_hasParsedPages )
{
ParsePages();
_hasParsedPages = true;
}
}
/// <summary>
/// This method parses the part pulling out the Page Referneces
/// and populates the _pageCache
/// </summary>
private
void
ParsePages()
{
using (Stream stream = _metroPart.GetStream(FileMode.Open))
{
//
// If the stream is empty there are no pages to parse
//
if (stream.Length > 0)
{
XmlTextReader reader = new XmlTextReader(stream);
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == XpsS0Markup.PageContent)
{
string attribute = reader.GetAttribute(XmlTags.Source);
if (attribute != null)
{
Uri relativeUri = new Uri(attribute, UriKind.Relative);
AddPageToCache(PackUriHelper.ResolvePartUri(Uri, relativeUri));
}
}
}
}
}
}
private
IXpsFixedPageReader
AddPageToCache( Uri pageUri )
{
PackagePart pagePart = CurrentXpsManager.GetPart(pageUri);
if (pagePart == null)
{
throw new XpsPackagingException(SR.ReachPackaging_PartNotFound);
}
if (!pagePart.ValidatedContentType().AreTypeAndSubTypeEqual(XpsS0Markup.FixedPageContentType))
{
throw new XpsPackagingException(SR.ReachPackaging_NotAFixedPage);
}
//
// Create the reader/writer for the part
//
IXpsFixedPageReader pageReader = new XpsFixedPageReaderWriter(CurrentXpsManager, this, pagePart, null, _pageCache.Count+1);
//
// Cache the new reader/writer for later
//
_pageCache.Add(pageReader );
return pageReader;
}
private
void
EnsureThumbnail()
{
if( _thumbnail == null )
{
_thumbnail = CurrentXpsManager.EnsureThumbnail( this, _metroPart );
}
}
private
void
EnsureSignatureDefinitions()
{
// if _xpsSignaturs is not null we have already initialized this
//
if( null != _signatureDefinitions)
{
return;
}
_signatureDefinitions = new Collection<XpsSignatureDefinition>();
PackagePart sigDefPart =
CurrentXpsManager.GetSignatureDefinitionPart(Uri);
if( sigDefPart != null )
{
ParseSignaturePart( sigDefPart, _signatureDefinitions );
}
}
private
void
EnsureDocumentStructure()
{
// if _xpsSignaturs is not null we have already initialized this
//
if( null != _documentStructure)
{
return;
}
PackageRelationship documentStructureRelationship = null;
PackagePart documentStructurePart = null;
foreach (PackageRelationship rel in _metroPart.GetRelationshipsByType(XpsS0Markup.StructureRelationshipName))
{
if (documentStructureRelationship != null)
{
throw new InvalidDataException(SR.ReachPackaging_MoreThanOneDocStructure);
}
documentStructureRelationship = rel;
}
if (documentStructureRelationship != null)
{
Uri documentStructureUri = PackUriHelper.ResolvePartUri(documentStructureRelationship.SourceUri,
documentStructureRelationship.TargetUri);
if (CurrentXpsManager.MetroPackage.PartExists(documentStructureUri))
{
documentStructurePart = CurrentXpsManager.MetroPackage.GetPart(documentStructureUri);
_documentStructure = new XpsStructure(CurrentXpsManager, this, documentStructurePart);
}
}
}
private
void
ParseSignaturePart(
PackagePart sigDefPart,
Collection<XpsSignatureDefinition> sigDefCollection
)
{
using (XmlTextReader reader = new XmlTextReader(sigDefPart.GetStream(FileMode.Open)))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element &&
reader.Name == XpsS0Markup.SignatureDefinitions
)
{
ParseSignatureDefinitions(reader, sigDefCollection);
}
}
}
}
private
void
ParseSignatureDefinitions(
XmlReader reader,
Collection<XpsSignatureDefinition> sigDefCollection
)
{
bool endLoop = false;
while (!endLoop && reader.Read())
{
if( reader.NodeType == XmlNodeType.Element &&
reader.Name == XpsS0Markup.SignatureDefinition
)
{
XpsSignatureDefinition sigDef = new XpsSignatureDefinition();
sigDef.ReadXML(reader);
sigDefCollection.Add( sigDef );
}
if( reader.NodeType == XmlNodeType.EndElement &&
reader.Name == XpsS0Markup.SignatureDefinitions
)
{
endLoop = true;
}
}
}
private
void
WriteSignatureDefinitions()
{
PackagePart sigDefPart =
CurrentXpsManager.GetSignatureDefinitionPart(Uri);
if( sigDefPart == null )
{
sigDefPart = CurrentXpsManager.AddSignatureDefinitionPart( _metroPart );
}
using (Stream stream = sigDefPart.GetStream(FileMode.Create))
using (XmlTextWriter writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8))
{
writer.WriteStartDocument();
writer.WriteStartElement(XpsS0Markup.SignatureDefinitions,
XpsS0Markup.SignatureDefinitionNamespace);
foreach (XpsSignatureDefinition sigDef in _signatureDefinitions)
{
sigDef.WriteXML(writer);
}
writer.WriteEndElement();
}
_sigCollectionDirty = false;
}
#endregion Private methods
#region Private data
private PackagePart _metroPart;
private PrintTicket _printTicket;
private XmlPartEditor _partEditor;
private IList<String> _linkTargetStream;
private List<IXpsFixedPageReader> _pageCache;
//
// This variable is used to keep a count of pages written via AddFixedPage
//
private int _pagesWritten;
//
// This variable flags whether the PrintTicket property is
// committed. A writer can only commit this property once.
//
private bool _isPrintTicketCommitted;
//
// These variables are used to keep track of the parent
// and current child of this node for walking up and
// down the current tree. This is used be the flushing
// policy to do interleave flushing of parts correctly.
//
private INode _parentNode;
//
// This variable flags wehter the pageCashe
// has been populated by parsing the part for dependent pages
//
private bool _hasParsedPages;
//
// 0 based document number in the document sequence
//
private int _documentNumber;
private XpsThumbnail _thumbnail;
//
// Since the current page may add link target information
// we must track our current page
// for this reason we can not handle adding new page
// until the the current page has been committed
//
private XpsFixedPageReaderWriter _currentPage;
//
// A cached list of Signature Definitions
//
private Collection<XpsSignatureDefinition> _signatureDefinitions;
//
// Boolean indicating whetehr _signatureDefinitions collection
// has been changed
//
private bool _sigCollectionDirty;
private XpsStructure _documentStructure;
#endregion Private data
#region Internal properties
/// <summary>
/// Gets a reference to the XmlWriter for the Metro part
/// that represents this fixed document.
/// </summary>
internal System.Xml.XmlWriter XmlWriter
{
get
{
_partEditor.DoesWriteStartEndTags = false;
return _partEditor.XmlWriter;
}
}
#endregion Internal properties
#region INode implementation
void
INode.Flush(
)
{
//
// Commit the PrintTicket (if necessary)
//
CommitPrintTicket();
//
// Create the relationship between the package and the tumbnail
//
if( _thumbnail != null )
{
_thumbnail = null;
}
}
void
INode.CommitInternal(
)
{
CommitInternal();
}
PackagePart
INode.GetPart(
)
{
return _metroPart;
}
#endregion INode implementation
#region IDisposable implementation
void
IDisposable.Dispose(
)
{
CommitInternal();
}
#endregion IDisposable implementation
}
}
|