Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / AlphaFlattener / metrodevice.cs / 2 / metrodevice.cs
//------------------------------------------------------------------------------ // Microsoft Printing // Copyright (c) Microsoft Corporation, 2004 // // File: MetroDevice.cs // // History: // [....]: 09/24/2004 Created //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; // for ArrayList using System.Windows; // for Rect WindowsBase.dll using System.Windows.Media; // for Geometry, Brush, ImageData. PresentationCore.dll using System.Windows.Media.Imaging; using System.Windows.Shapes; // for Glyphs PresentationFramework.dll using System.Windows.Xps.Serialization; using System.Printing; using System.Printing.Interop; using System.Security.Permissions; using System.Security; using System.Drawing.Printing; namespace Microsoft.Internal.AlphaFlattener { ////// /// internal class MetroDevice0 { [Flags] private enum DeviceState { NoChange = 0, Init = 1, DocStarted = 2, PageStarted = 4 }; private enum PushType { Opacity, Clip, Transform }; private DeviceState _state; private CanvasPrimitive _page; // Page private CanvasPrimitive _root; // Current root private BrushProxy _opacityMask; // Current layer OpacityMask private double _opacity; // Current layer Opacity private Geometry _clip; // Current layer Clip private Stack _stack; #if UNIT_TEST static private bool s_first = true; #endif ////// /// public MetroDevice0() { #if UNIT_TEST if (s_first) { s_first = false; RectangleIntersection.UnitTest(); } #endif _state = DeviceState.Init; } private void AssertState(DeviceState state, DeviceState next) { if ((_state & state) != state) { throw new InvalidOperationException(); } if (next != DeviceState.NoChange) { _state = next; } } ////// /// public void StartDocument() { AssertState(DeviceState.Init, DeviceState.DocStarted); } ////// /// public void EndDocument() { AssertState(DeviceState.DocStarted, DeviceState.Init); } ////// /// public void AbortDocument() { _state = DeviceState.Init; } ////// /// public bool StartPage() { AssertState(DeviceState.DocStarted, DeviceState.PageStarted); _page = new CanvasPrimitive(); _root = _page; _stack = new Stack(); _opacity = 1; _opacityMask = null; _clip = null; return true; } ////// Start Tree/alpha flattening and send result to ILegacyDevice interface /// public void FlushPage(ILegacyDevice sink, double width, double height, NullableoutputQuality) { AssertState(DeviceState.PageStarted, DeviceState.DocStarted); if (_stack.Count != 0) { throw new InvalidOperationException(); } if (sink != null) { Flattener.Convert(_root, sink, width, height, 96, 96, outputQuality); } } public void DrawGeometry(Brush brush, Pen pen, Geometry geometry) { // Ignore total transparent primitive if (Utility.IsTransparent(_opacity) || ((brush == null) && (pen == null || pen.Brush == null)) || (geometry == null)) { return; } // Split if having both pen and brush if ((brush != null) && (pen != null)) // if (!Utility.IsOpaque(_opacity) || (_opacityMask != null)) { // Push a canvas to handle geometry with brush + pen properly Push(Matrix.Identity, null, 1.0, null, Rect.Empty, false); DrawGeometry(brush, null, geometry); DrawGeometry(null, pen, geometry); Pop(); return; } AssertState(DeviceState.PageStarted, DeviceState.NoChange); GeometryPrimitive g = new GeometryPrimitive(); g.Geometry = geometry; g.Clip = _clip; g.Opacity = _opacity; g.OpacityMask = _opacityMask; int needBounds = 0; // 1 for fill, 2 for stroke if (brush != null) { // Fix bug 1427695: Need bounds for non-SolidColorBrushes to enable rebuilding Brush from BrushProxy. if (!(brush is SolidColorBrush)) { needBounds |= 1; } } if ((pen != null) && (pen.Brush != null)) { if (!(pen.Brush is SolidColorBrush)) { needBounds |= 2; } } if (g.OpacityMask != null) { if (g.OpacityMask.BrushList == null && !(g.OpacityMask.Brush is SolidColorBrush)) { if (pen != null) { needBounds |= 2; } else { needBounds |= 1; } } } Rect bounds = g.GetRectBounds((needBounds & 1) != 0); if (brush != null) { g.Brush = BrushProxy.CreateBrush(brush, bounds); } if ((needBounds & 2) != 0) { bounds = geometry.GetRenderBounds(pen); } if ((pen != null) && (pen.Brush != null)) { g.Pen = PenProxy.CreatePen(pen, bounds); } if (g.OpacityMask != null) { if (!g.OpacityMask.MakeBrushAbsolute(bounds)) { // Fix bug 1463955: Brush has become empty; replace with transparent brush. g.OpacityMask = BrushProxy.CreateColorBrush(Colors.Transparent); } } // Optimization: Unfold primitive DrawingBrush when possible to avoid rasterizing it. Primitive primitive = g.UnfoldDrawingBrush(); if (primitive != null) { _root.Children.Add(primitive); } } public void DrawImage(ImageSource image, Rect rectangle) { if (image == null) return; AssertState(DeviceState.PageStarted, DeviceState.NoChange); ImagePrimitive g = new ImagePrimitive(); g.Image = new ImageProxy((BitmapSource)image); g.DstRect = rectangle; g.Clip = _clip; g.Opacity = _opacity; g.OpacityMask = _opacityMask; _root.Children.Add(g); } public void DrawGlyphRun(Brush foreground, GlyphRun glyphRun) { if (foreground == null) return; AssertState(DeviceState.PageStarted, DeviceState.NoChange); GlyphPrimitive g = new GlyphPrimitive(); bool needBounds = false; if (foreground != null && !(foreground is SolidColorBrush)) { needBounds = true; } g.GlyphRun = glyphRun; g.Brush = BrushProxy.CreateBrush(foreground, g.GetRectBounds(needBounds)); g.Clip = _clip; g.Opacity = _opacity; g.OpacityMask = _opacityMask; // Optimization: Unfold primitive DrawingBrush when possible to avoid rasterizing it. Primitive primitive = g.UnfoldDrawingBrush(); if (primitive != null) { _root.Children.Add(primitive); } } public void Push(Matrix transform, Geometry clip, double opacity, Brush opacityMask, Rect maskBounds, bool onePrimitive) { AssertState(DeviceState.PageStarted, DeviceState.NoChange); opacity = Utility.NormalizeOpacity(opacity); if (!Utility.IsValid(transform)) { // treat as invisible subtree opacity = 0.0; transform = Matrix.Identity; } _stack.Push(_root); _stack.Push(_clip); _stack.Push(_opacity); _stack.Push(_opacityMask); bool noTrans = transform.IsIdentity; if (onePrimitive && noTrans && (opacityMask == null)) { bool empty; _clip = Utility.Intersect(_clip, clip, Matrix.Identity, out empty); _opacity *= opacity; _opacityMask = null; if (empty) { _opacity = 0; } } else { CanvasPrimitive c = new CanvasPrimitive(); if (noTrans) { c.Transform = Matrix.Identity; } else { c.Transform = transform; Matrix invertTransform = transform; invertTransform.Invert(); _clip = Utility.TransformGeometry(_clip, invertTransform); // transform inherited clip to this level } bool empty; c.Clip = Utility.Intersect(clip, _clip, Matrix.Identity, out empty); // Combined with inherited attributes c.Opacity = opacity * _opacity; if (empty) { c.Opacity = 0; // Invisible } if (opacityMask != null) { double op; if (Utility.ExtractOpacityMaskOpacity(opacityMask, out op, maskBounds)) { c.Opacity = opacity * _opacity * op; } else { c.OpacityMask = BrushProxy.CreateOpacityMaskBrush(opacityMask, maskBounds); } } _root.Children.Add(c); _root = c; _clip = null; _opacity = 1.0; _opacityMask = null; } } public void Pop() { AssertState(DeviceState.PageStarted, DeviceState.NoChange); _opacityMask = _stack.Pop() as BrushProxy; _opacity = (double) _stack.Pop(); _clip = _stack.Pop() as Geometry; _root = _stack.Pop() as CanvasPrimitive; } #if COMMENT void Comment(string message) { } #endif } /// /// Main interface to NGCSerializationManager, and glue flatteners and GDIExporter together /// /// 1) Implements IMetroDrawingContext interface /// 2) Passes drawing primitives to MetroDevice0 to build a primitive tree /// 3) In FlushPage, calls tree flattener to flat primitive tree to a linear display list /// 4) In FlushPage, calls alpha flattener to resolve transparency and send down result on the fly to GDIExporter which implements the ILegacyDevice interface /// 5) In FlushPage, calls GDIExporter.EndPage to finish printing a page /// 6) Supporting Testing hook to serialize alpha flattening result /// internal class MetroToGdiConverter : IMetroDrawingContext { static protected object s_TestingHook; protected MetroDevice0 m_Flattener; protected ILegacyDevice m_GDIExporter; protected PrintQueue m_PrintQueue; protected PrintTicketConverter m_Converter; // Expensive to create, cache it ////// Critical : Information got by calling GetDevmode /// [SecurityCritical] protected byte[] m_Devmode; // settings captured from current PrintTicket protected double m_PageWidth; protected double m_PageHeight; protected Nullablem_OutputQuality; public MetroToGdiConverter(PrintQueue queue) { if (queue == null) throw new ArgumentNullException("queue"); m_PrintQueue = queue; m_Flattener = new MetroDevice0(); m_GDIExporter = queue.GetLegacyDevice(); } /// /// Critical : It asserts PrintingPermission /// [SecurityCritical] private byte[] GetDevmode(PrintTicket ticket) { Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXGETDEVMODEGUID); (new PrintingPermission(PrintingPermissionLevel.DefaultPrinting)).Assert(); // BlessedAssert byte[] result = null; try { if (m_Converter == null) { m_Converter = new PrintTicketConverter(m_PrintQueue.FullName, m_PrintQueue.ClientPrintSchemaVersion); } result = m_Converter.ConvertPrintTicketToDevMode(ticket, BaseDevModeType.UserDefault); } finally { PrintingPermission.RevertAssert(); } Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXGETDEVMODEGUID); return result; } ////// Captures settings from complete PrintTickets. /// /// ////// PrintTicket changes are communicated through StartDocument and StartPage, which receive /// complete tickets (the merge of tickets at all levels). Lack of change is indicated by /// null. Here we capture settings from PrintTicket for use in flattening and by GDIExporter. /// private void CaptureTicketSettings(PrintTicket ticket) { if (ticket == null) { // ticket has not changed since last capture; keep existing settings } else { m_OutputQuality = ticket.OutputQuality; // // Fix bug: 1396328, 1394678: Incorrect page dimensions used for clipping. // // PrintTicket contains the application-requested page dimensions. The printer // may print to a page of different dimensions; that information is returned in // PrintCapabilities, and is what we need to use for clipping. // PrintCapabilities capabilities = m_PrintQueue.GetPrintCapabilities(ticket); m_PageWidth = capabilities.OrientedPageMediaWidth.GetValueOrDefault(816); m_PageHeight = capabilities.OrientedPageMediaHeight.GetValueOrDefault(1056); } } ////// Critical : It calls GetDevmode and give away the print job id /// /// WasTreatAsSafe: DEVMODE is passed to GDI, not leaked [SecurityCritical] public int StartDocument(string jobName, PrintTicket ticket) { int jobIdentifier = 0; Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXSTARTDOCGUID); if (ticket == null) { ticket = m_PrintQueue.UserPrintTicket; } CaptureTicketSettings(ticket); m_Flattener.StartDocument(); if (s_TestingHook == null) { m_Devmode = GetDevmode(ticket); jobIdentifier = m_GDIExporter.StartDocument(m_PrintQueue.FullName, jobName, Configuration.OutputFile, m_Devmode); } Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXSTARTDOCGUID); return jobIdentifier; } public void EndDocument() { Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXENDDOCGUID); m_Flattener.EndDocument(); if (s_TestingHook == null) { m_GDIExporter.EndDocument(); } if (m_Converter != null) { m_Converter.Dispose(); m_Converter = null; } Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXENDDOCGUID); } ////// Critical : It calls GetDevmode /// TreatAsSafe: DEVMODE is passed to GDI, not leaked /// [SecurityCritical, SecurityTreatAsSafe] public void CreateDeviceContext(string jobName, PrintTicket ticket) { if (ticket == null) { ticket = m_PrintQueue.UserPrintTicket; } CaptureTicketSettings(ticket); m_Devmode = GetDevmode(ticket); m_GDIExporter.CreateDeviceContext(m_PrintQueue.FullName, jobName, m_Devmode); } public void DeleteDeviceContext() { m_GDIExporter.DeleteDeviceContext(); } public void StartDocumentWithoutCreatingDC(String jobName) { m_Flattener.StartDocument(); String printerName = m_PrintQueue.FullName; m_GDIExporter.StartDocumentWithoutCreatingDC(printerName, jobName, Configuration.OutputFile); } public string ExtEscGetName() { return m_GDIExporter.ExtEscGetName(); } public bool ExtEscMXDWPassThru() { return m_GDIExporter.ExtEscMXDWPassThru(); } public void AbortDocument() { m_Flattener.AbortDocument(); m_GDIExporter.EndDocument(); if (m_Converter != null) { m_Converter.Dispose(); m_Converter = null; } } ////// Critical : It calls GetDevmode /// TreatAsSafe: DEVMODE is passed to GDI, not leaked /// [SecurityCritical, SecurityTreatAsSafe] public void StartPage(PrintTicket ticket) { Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXSTARTPAGEGUID); CaptureTicketSettings(ticket); if (m_Flattener.StartPage()) { if (s_TestingHook == null) { if (ticket != null) { m_GDIExporter.StartPage(GetDevmode(ticket), Configuration.RasterizationDPI); } else { m_GDIExporter.StartPage(null, Configuration.RasterizationDPI); } } } Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXSTARTPAGEGUID); } public void FlushPage() { Toolbox.StartEvent(Toolbox.DRXFLUSHPAGEGUID); ILegacyDevice ioc = m_GDIExporter; if (s_TestingHook != null) { DrawingContext dc = s_TestingHook as DrawingContext; if (dc != null) { // Send alpha flattening output to a DrawingContext for testing ioc = new OutputContext(dc); } } m_Flattener.FlushPage(ioc, m_PageWidth, m_PageHeight, m_OutputQuality); if (s_TestingHook == null) { Toolbox.StartEvent(MS.Utility.EventTraceGuidId.DRXENDPAGEGUID); m_GDIExporter.EndPage(); Toolbox.EndEvent(MS.Utility.EventTraceGuidId.DRXENDPAGEGUID); } Toolbox.EndEvent(Toolbox.DRXFLUSHPAGEGUID); } void IMetroDrawingContext.DrawGeometry(Brush brush, Pen pen, Geometry geometry) { m_Flattener.DrawGeometry(brush, pen, geometry); } void IMetroDrawingContext.DrawImage(ImageSource image, Rect rectangle) { m_Flattener.DrawImage(image, rectangle); } void IMetroDrawingContext.DrawGlyphRun(Brush foreground, GlyphRun glyphRun) { m_Flattener.DrawGlyphRun(foreground, glyphRun); } void IMetroDrawingContext.Push( Matrix transform, Geometry clip, double opacity, Brush opacityMask, Rect maskBounds, bool onePrimitive, // serialization attributes String nameAttr, Visual node, Uri navigateUri, EdgeMode edgeMode ) { m_Flattener.Push(transform, clip, opacity, opacityMask, maskBounds, onePrimitive); } void IMetroDrawingContext.Pop() { m_Flattener.Pop(); } void IMetroDrawingContext.Comment(string message) { } ////// Called before StartDocument to by-pass GDIExporter and send result to DrawingContext /// /// static public void TestingHook(Object obj) { if (obj != null) { s_TestingHook = obj as DrawingContext; } } } } // end of namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ColumnWidthChangingEvent.cs
- ButtonField.cs
- ResourceExpressionEditor.cs
- ImageInfo.cs
- Point.cs
- StorageEntityContainerMapping.cs
- DefaultHttpHandler.cs
- SQLBinary.cs
- CursorConverter.cs
- SrgsGrammarCompiler.cs
- ElapsedEventArgs.cs
- HandoffBehavior.cs
- KeyValueConfigurationElement.cs
- TableStyle.cs
- EllipticalNodeOperations.cs
- SourceInterpreter.cs
- ValuePattern.cs
- FilterQueryOptionExpression.cs
- ClipboardData.cs
- Oci.cs
- ReferenceSchema.cs
- StorageScalarPropertyMapping.cs
- SoapIgnoreAttribute.cs
- SerialStream.cs
- Button.cs
- MasterPageCodeDomTreeGenerator.cs
- Win32.cs
- Win32Native.cs
- ModelPropertyCollectionImpl.cs
- ZipFileInfo.cs
- RequestCachingSection.cs
- VisualState.cs
- PenThread.cs
- PreviewKeyDownEventArgs.cs
- AutoGeneratedFieldProperties.cs
- ListBoxItemWrapperAutomationPeer.cs
- EventHandlerList.cs
- Int32Rect.cs
- TransformerInfoCollection.cs
- InfoCardSymmetricCrypto.cs
- AspNetCompatibilityRequirementsAttribute.cs
- InheritanceContextChangedEventManager.cs
- SecurityCredentialsManager.cs
- mediapermission.cs
- ClientBuildManagerTypeDescriptionProviderBridge.cs
- SamlAction.cs
- NavigationExpr.cs
- SchemaElement.cs
- NavigationPropertyEmitter.cs
- XmlNamespaceMapping.cs
- TextDecorationCollection.cs
- ManagementScope.cs
- WebPartsPersonalizationAuthorization.cs
- PatternMatcher.cs
- MethodExpr.cs
- AvTraceDetails.cs
- XamlReaderHelper.cs
- MimeMapping.cs
- DataGridViewRowContextMenuStripNeededEventArgs.cs
- securestring.cs
- X509CertificateEndpointIdentity.cs
- AuthorizationSection.cs
- ProfileEventArgs.cs
- LinearQuaternionKeyFrame.cs
- VSWCFServiceContractGenerator.cs
- PermissionListSet.cs
- ScriptServiceAttribute.cs
- XmlTextReaderImplHelpers.cs
- SchemaLookupTable.cs
- XmlLangPropertyAttribute.cs
- Pkcs9Attribute.cs
- xsdvalidator.cs
- FixedSOMGroup.cs
- DataSourceHelper.cs
- ServiceObjectContainer.cs
- HyperLinkDesigner.cs
- RayHitTestParameters.cs
- XmlNodeChangedEventArgs.cs
- SqlBuilder.cs
- EncodingTable.cs
- ReadOnlyHierarchicalDataSourceView.cs
- Main.cs
- EventLogPermissionEntryCollection.cs
- IndexOutOfRangeException.cs
- WmlMobileTextWriter.cs
- DataGridViewColumnCollection.cs
- SliderAutomationPeer.cs
- LocalBuilder.cs
- ReachNamespaceInfo.cs
- EntityDesignerDataSourceView.cs
- CustomAssemblyResolver.cs
- WebBrowserProgressChangedEventHandler.cs
- TextEditorCopyPaste.cs
- EntityException.cs
- NamedPipeHostedTransportConfiguration.cs
- HttpClientCredentialType.cs
- RowBinding.cs
- DeferredSelectedIndexReference.cs
- PropertyValueUIItem.cs
- AutomationEvent.cs