| File: Serialization\Manager\XpsOMSerializationManager.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using MS.Utility; using System.ComponentModel; using System.Printing; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Xps.Packaging; using System.Xml; namespace System.Windows.Xps.Serialization { internal class XpsOMSerializationManager : PackageSerializationManager, IXpsSerializationManager { #region Constructor public XpsOMSerializationManager( XpsOMPackagingPolicy xpsOMManager, bool batchMode ): base() { _packagingPolicy = xpsOMManager; _isBatchMode = batchMode; _reachSerializationServices = new ReachSerializationServices(); _reachSerializationServices.RegisterNameSpacesForTypes(); _reachSerializationServices.RegisterSerializableDependencyPropertiesForReachTypes(); _reachSerializationServices.RegisterNoneSerializableClrPropertiesForReachTypes(); _visualSerializationService = new VisualSerializationService(this); XpsResourcePolicy resourcePolicy = new XpsResourcePolicy(XpsResourceSharing.NoResourceSharing); resourcePolicy.RegisterService(new XpsImageSerializationService(), typeof(XpsImageSerializationService)); resourcePolicy.RegisterService(new XpsFontSerializationService(_packagingPolicy), typeof(XpsFontSerializationService)); _resourcePolicy = resourcePolicy; SetFontSubsettingPolicy(FontSubsetterCommitPolicies.CommitPerPage); SetFontSubsettingCountPolicy(4); } #endregion Constructor #region PackageSerializationManager override public override void SaveAsXaml( object serializedObject ) { Toolbox.EmitEvent(EventTrace.Event.WClientDRXSaveXpsBegin); if (_packagingPolicy.IsValid) { XmlWriter pageWriter = null; ArgumentNullException.ThrowIfNull(serializedObject); if (!XpsSerializationManager.IsSerializedObjectTypeSupported(serializedObject, _isBatchMode)) { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } if (serializedObject is DocumentPaginator) { if ((serializedObject as DocumentPaginator).Source is FixedDocument && serializedObject.GetType().ToString().Contains("FixedDocumentPaginator")) { serializedObject = (serializedObject as DocumentPaginator).Source; } else if ((serializedObject as DocumentPaginator).Source is FixedDocumentSequence && serializedObject.GetType().ToString().Contains("FixedDocumentSequencePaginator")) { serializedObject = (serializedObject as DocumentPaginator).Source; } } if (_simulator == null) { _simulator = new XpsOMHierarchySimulator(this, serializedObject); } if (!_isSimulating) { _simulator.BeginConfirmToXPSStructure(_isBatchMode); _isSimulating = true; } if (_isBatchMode) { pageWriter = _simulator.SimulateBeginFixedPage(); } ReachSerializer reachSerializer = GetSerializer(serializedObject); if (reachSerializer != null) { //Things that need to be done at this stage //1. Setting the stack context //2. Setting the root of the graph for future references reachSerializer.SerializeObject(serializedObject); if (_isBatchMode) { _simulator.SimulateEndFixedPage(pageWriter); } else { _simulator.EndConfirmToXPSStructure(_isBatchMode); } } else { throw new XpsSerializationException(SR.ReachSerialization_NoSerializer); } } Toolbox.EmitEvent(EventTrace.Event.WClientDRXSaveXpsEnd); } internal override Type GetSerializerType( Type objectType ) { Type serializerType = null; if ((serializerType = base.GetSerializerType(objectType)) == null) { if (typeof(System.Windows.Documents.FixedDocument).IsAssignableFrom(objectType)) { serializerType = typeof(XpsOMFixedDocumentSerializer); } else if (typeof(System.Windows.Documents.PageContentCollection).IsAssignableFrom(objectType)) { serializerType = typeof(ReachPageContentCollectionSerializer); } else if (typeof(System.Windows.Documents.PageContent).IsAssignableFrom(objectType)) { serializerType = typeof(ReachPageContentSerializer); } else if (typeof(System.Windows.Controls.UIElementCollection).IsAssignableFrom(objectType)) { serializerType = typeof(ReachUIElementCollectionSerializer); } else if (typeof(System.Windows.Documents.FixedPage).IsAssignableFrom(objectType)) { serializerType = typeof(XpsOMFixedPageSerializer); } else if (typeof(System.Windows.Documents.FixedDocumentSequence).IsAssignableFrom(objectType)) { serializerType = typeof(XpsOMDocumentSequenceSerializer); } else if (typeof(System.Windows.Documents.DocumentReferenceCollection).IsAssignableFrom(objectType)) { serializerType = typeof(ReachDocumentReferenceCollectionSerializer); } else if (typeof(System.Windows.Documents.DocumentReference).IsAssignableFrom(objectType)) { serializerType = typeof(ReachDocumentReferenceSerializer); } else if (typeof(System.Windows.Documents.DocumentPaginator).IsAssignableFrom(objectType)) { serializerType = typeof(XpsOMDocumentPaginatorSerializer); } else if (typeof(System.Windows.Documents.DocumentPage).IsAssignableFrom(objectType)) { serializerType = typeof(XpsOMDocumentPageSerializer); } else if (typeof(System.Windows.Media.Visual).IsAssignableFrom(objectType)) { serializerType = typeof(ReachVisualSerializer); } else if (typeof(System.Printing.PrintTicket).IsAssignableFrom(objectType)) { serializerType = typeof(PrintTicketSerializer); } } return serializerType; } /// <summary> /// /// </summary> internal override TypeConverter GetTypeConverter( Object serializedObject ) { TypeConverter typeConverter = null; if (typeof(BitmapSource).IsAssignableFrom(serializedObject.GetType())) { return new ImageSourceTypeConverter(); } else if (typeof(GlyphRun).IsAssignableFrom(serializedObject.GetType())) { return new FontTypeConverter(); } else if (typeof(Color).IsAssignableFrom(serializedObject.GetType())) { return new ColorTypeConverter(); } else { typeConverter = base.GetTypeConverter(serializedObject); } return typeConverter; } /// <summary> /// /// </summary> internal override TypeConverter GetTypeConverter( Type serializedObjectType ) { TypeConverter typeConverter = null; if (typeof(BitmapSource).IsAssignableFrom(serializedObjectType)) { return new ImageSourceTypeConverter(); } else if (typeof(GlyphRun).IsAssignableFrom(serializedObjectType)) { return new FontTypeConverter(); } else if (typeof(Color).IsAssignableFrom(serializedObjectType)) { return new ColorTypeConverter(); } else { typeConverter = base.GetTypeConverter(serializedObjectType); } return typeConverter; } internal override bool CanSerializeDependencyProperty( Object serializableObject, TypeDependencyPropertyCache dependencyProperty ) { return XpsSerializationManager.CanSerializeDependencyProperty(serializableObject, dependencyProperty, _reachSerializationServices); } internal override bool CanSerializeClrProperty( Object serializableObject, TypePropertyCache property ) { return XpsSerializationManager.CanSerializeClrProperty(serializableObject, property, _reachSerializationServices); } internal override string GetXmlNSForType( Type objectType ) { return (string)_reachSerializationServices.TypesXmlNSMapping[objectType]; } internal override Xml.XmlWriter AcquireXmlWriter(Type writerType) { XmlWriter xmlWriter = null; if (_packagingPolicy != null) { if (writerType == typeof(FixedPage)) { _currentFixedPageWriterRef++; xmlWriter = _packagingPolicy.AcquireXmlWriterForFixedPage(); } else { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } } return xmlWriter; } internal void signalReleaseToFontService( Type writerType ) { bool subsetComplete = false; int refCnt = DecrementRefCntByType(writerType); // signal the font sub-setter that we completed a node if (_resourcePolicy != null) { XpsFontSerializationService fontService = (XpsFontSerializationService)_resourcePolicy.GetService(typeof(XpsFontSerializationService)); // // The font subsetter will determine if based on this // signal we have completed a subset // if (fontService != null && refCnt == 0) { subsetComplete = fontService.SignalCommit(writerType); } } } internal void ReleaseXpsOMWriterForFixedDocumentSequence() { Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterStart); signalReleaseToFontService(typeof(FixedDocumentSequence)); _packagingPolicy?.CloseXpsOMPackageWriter(); Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterEnd); } internal void ReleaseXpsOMWriterForFixedDocument() { Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterStart); signalReleaseToFontService(typeof(FixedDocument)); _packagingPolicy?.ReleaseXpsOMWriterForFixedDocument(); Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterEnd); } internal override void ReleaseXmlWriter( Type writerType ) { Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterStart); // // Allow the packaging policy to release the stream // if (_packagingPolicy != null) { if (writerType == typeof(FixedPage)) { _packagingPolicy.ReleaseXmlWriterForFixedPage(); } else { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } } signalReleaseToFontService(writerType); Toolbox.EmitEvent(EventTrace.Event.WClientDRXReleaseWriterEnd); } internal override XpsResourceStream AcquireResourceStream( Type resourceType ) { throw new NotImplementedException(); } internal override XpsResourceStream AcquireResourceStream( Type resourceType, string resourceID ) { XpsResourceStream resourceStream = null; if (_packagingPolicy != null) { if (resourceType == typeof(GlyphRun)) { resourceStream = _packagingPolicy.AcquireResourceStreamForXpsFont(resourceID); } else if (resourceType == typeof(BitmapSource)) { resourceStream = _packagingPolicy.AcquireResourceStreamForXpsImage(resourceID); } else if (resourceType == typeof(ColorContext)) { resourceStream = _packagingPolicy.AcquireResourceStreamForXpsColorContext(resourceID); } else if (resourceType == typeof(ResourceDictionary)) { resourceStream = _packagingPolicy.AcquireResourceStreamForXpsResourceDictionary(resourceID); } else { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } } return resourceStream; } internal override void ReleaseResourceStream( Type resourceType ) { if (_packagingPolicy != null) { if (resourceType == typeof(GlyphRun)) { _packagingPolicy.ReleaseResourceStreamForXpsFont(); } else if (resourceType == typeof(BitmapSource)) { _packagingPolicy.ReleaseResourceStreamForXpsImage(); } else if (resourceType == typeof(ColorContext)) { _packagingPolicy.ReleaseResourceStreamForXpsColorContext(); } else if (resourceType == typeof(ResourceDictionary)) { _packagingPolicy.ReleaseResourceStreamForXpsResourceDictionary(); } else { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } } } /// <summary> /// We must implement this method from abstract class PackageSerializationManager, it is /// actually not used during printing/serialization, so it should throw if it is ever called /// </summary> internal override void ReleaseResourceStream( Type resourceType, string resourceID ) { throw new NotImplementedException(); } /// <summary> /// It is no longer necessary to add the relationships explicitly since XpsOM will /// do it automatically, however, the serialization engine will still call into this /// method, so just no-op and continue. /// </summary> internal override void AddRelationshipToCurrentPage( Uri targetUri, string relationshipName ) { return; } internal override BasePackagingPolicy PackagingPolicy { get { return _packagingPolicy; } } internal override XpsResourcePolicy ResourcePolicy { get { return _resourcePolicy; } } #endregion PackageSerializationManager override #region Private methods /// <summary> /// Sets the Font subsetting policy on the /// Font Subset service /// </summary> private void SetFontSubsettingPolicy(FontSubsetterCommitPolicies policy) { IServiceProvider resourceServiceProvider = (IServiceProvider)ResourcePolicy; XpsFontSerializationService fontService = (XpsFontSerializationService)resourceServiceProvider.GetService(typeof(XpsFontSerializationService)); if (fontService != null) { XpsFontSubsetter fontSubsetter = fontService.FontSubsetter; fontSubsetter.SetSubsetCommitPolicy(policy); } } internal virtual void Commit() { if (_isBatchMode && _isSimulating && _packagingPolicy.IsValid) { _simulator.EndConfirmToXPSStructure(_isBatchMode); } } /// <summary> /// Sets the Font subsetting count policy on the /// Font Subset service. This is used to determine /// how many page or document signals are required before /// the subsetted font is flushed /// </summary> private void SetFontSubsettingCountPolicy(int countPolicy) { IServiceProvider resourceServiceProvider = (IServiceProvider)ResourcePolicy; XpsFontSerializationService fontService = (XpsFontSerializationService)resourceServiceProvider.GetService(typeof(XpsFontSerializationService)); if (fontService != null) { XpsFontSubsetter fontSubsetter = fontService.FontSubsetter; fontSubsetter.SetSubsetCommitCountPolicy(countPolicy); } } private int DecrementRefCntByType(Type writerType) { int refCnt = 0; if (writerType == typeof(FixedDocumentSequence)) { refCnt = --_currentDocumentSequenceWriterRef; } else if (writerType == typeof(FixedDocument)) { refCnt = --_currentFixedDocumentWriterRef; } else if (writerType == typeof(FixedPage)) { refCnt = --_currentFixedPageWriterRef; } else { throw new XpsSerializationException(SR.ReachSerialization_NotSupported); } return refCnt; } #endregion Private methods #region Internal methods internal void EnsureXpsOMPackageWriter() { _currentDocumentSequenceWriterRef++; _packagingPolicy.EnsureXpsOMPackageWriter(); } internal void StartNewDocument() { _currentFixedDocumentWriterRef++; _packagingPolicy.StartNewDocument(); } internal void OnXPSSerializationPrintTicketRequired( object operationState ) { XpsSerializationPrintTicketRequiredEventArgs e = operationState as XpsSerializationPrintTicketRequiredEventArgs; if (XpsSerializationPrintTicketRequired != null) { e.Modified = true; XpsSerializationPrintTicketRequired(this, e); } } internal void OnXPSSerializationProgressChanged( object operationState ) { XpsSerializationProgressChangedEventArgs e = operationState as XpsSerializationProgressChangedEventArgs; if (XpsSerializationProgressChanged != null) { XpsSerializationProgressChanged(this, e); } } internal void RegisterPageStart() { if (_pageStartState) { throw new XpsSerializationException(SR.ReachSerialization_FixedPageInPage); } // // Entering Page Started state // _pageStartState = true; // // Increment the number of documents serialized // _pageNumber += 1; } internal void RegisterPageEnd() { // // Exiting Page Started state // _pageStartState = false; } internal void RegisterDocumentSequenceStart() { _documentNumber = 0; } internal void RegisterDocumentSequenceEnd() { // // It is invalid to have a document sequence with no fixed documents // If no fixed documents have been searialzed throw // if (_documentNumber <= 0) { throw new XpsSerializationException(SR.ReachSerialization_NoFixedDocuments); } } internal void RegisterDocumentStart() { if( _documentStartState ) { throw new XpsSerializationException(SR.ReachSerialization_FixedDocumentInDocument); } if( _pageStartState) { throw new XpsSerializationException(SR.ReachSerialization_FixedDocumentInPage); } // // Entering Document Started state // _documentStartState = true; // // Increment the number of documents serialized // _documentNumber += 1; // // Clearing the number of pages for this document // _pageNumber = 0; } internal void RegisterDocumentEnd() { // // It is invalid to have a document with no fixed pages // If no fixed pages have been searialzed throw // if (_pageNumber <= 0) { throw new XpsSerializationException(SR.ReachSerialization_NoFixedPages); } // // Exiting Document Started state // _documentStartState = false; } #endregion Internal methods #region IXpsSerializationManager implementation void IXpsSerializationManager.OnXPSSerializationPrintTicketRequired( object operationState ) { OnXPSSerializationPrintTicketRequired(operationState); } void IXpsSerializationManager.OnXPSSerializationProgressChanged( object operationState ) { OnXPSSerializationProgressChanged(operationState); } void IXpsSerializationManager.RegisterPageStart() { RegisterPageStart(); } void IXpsSerializationManager.RegisterPageEnd() { RegisterPageEnd(); } PrintTicket IXpsSerializationManager.FixedPagePrintTicket { get { return FixedPagePrintTicket; } set { FixedPagePrintTicket = value; } } Size IXpsSerializationManager.FixedPageSize { get { return FixedPageSize; } set { FixedPageSize = value; } } VisualSerializationService IXpsSerializationManager.VisualSerializationService { get { return VisualSerializationService; } } #endregion IXpsSerializationManager properties #region internal properties internal PrintTicket FixedPagePrintTicket { get { return _fixedPagePrintTicket; } set { _fixedPagePrintTicket = value; } } internal Size FixedPageSize { get { return _fixedPageSize; } set { _fixedPageSize = value; _packagingPolicy.FixedPageSize = _fixedPageSize; } } internal VisualSerializationService VisualSerializationService { get { return _visualSerializationService; } } /// <summary> /// Gets/Sets the hierarchy simulator used by this manager /// </summary> internal XpsOMHierarchySimulator Simulator { get { return _simulator; } set { _simulator = value; } } /// <summary> /// Gets/sets whether Xps hierachy simulation was necessary for this manager /// </summary> internal bool IsSimulating { get { return _isSimulating; } set { _isSimulating = value; } } /// <summary> /// Returns whether this manager is accepting multiple SaveAsXaml calls /// to serialize each Visual individually, this is done via VisualsToXpsDocument /// </summary> internal bool IsBatchMode { get { return _isBatchMode; } } #endregion internal properties #region Private members private XpsOMPackagingPolicy _packagingPolicy; private bool _isBatchMode; private XpsOMHierarchySimulator _simulator; private bool _isSimulating; private int _currentDocumentSequenceWriterRef; private int _currentFixedDocumentWriterRef; private int _currentFixedPageWriterRef; // // This counter is used to ensure at least one document is added // private int _documentNumber; // // This counter is used to ensure at least one page is added // This is reset by a document completing // private int _pageNumber; // // This flag is used to test if in document serialization // This is to prevent writing of a document in a document // private bool _documentStartState; // // This flag is used to test if in page serialization // This is to prevent writing of a page in a page // private bool _pageStartState; // // This print ticket is cached when we get it inside of the Page Content Serializer // and we need to retrieve it inside of the FixedPage Serializer // private PrintTicket _fixedPagePrintTicket; private Size _fixedPageSize = new Size(816, 1056); private XpsResourcePolicy _resourcePolicy; private ReachSerializationServices _reachSerializationServices; private VisualSerializationService _visualSerializationService; #endregion Private members #region internal events internal event XpsSerializationPrintTicketRequiredEventHandler XpsSerializationPrintTicketRequired; internal event XpsSerializationProgressChangedEventHandler XpsSerializationProgressChanged; #endregion } }