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
- GreenMethods.cs
- Action.cs
- TemplateBuilder.cs
- XmlAtomicValue.cs
- ZipIOModeEnforcingStream.cs
- AssemblyBuilder.cs
- InvokeMethod.cs
- SqlGenerator.cs
- XmlNullResolver.cs
- WindowsFormsSectionHandler.cs
- UpdatePanel.cs
- CodeTypeParameter.cs
- PlatformCulture.cs
- httpserverutility.cs
- ValidationHelper.cs
- QuaternionRotation3D.cs
- RowType.cs
- XmlSchemaSimpleType.cs
- ConstraintCollection.cs
- QueryInterceptorAttribute.cs
- SqlBooleanizer.cs
- StringSorter.cs
- SecurityTokenValidationException.cs
- SafeProcessHandle.cs
- ReferenceEqualityComparer.cs
- Effect.cs
- ImageListUtils.cs
- WebDisplayNameAttribute.cs
- SqlPersonalizationProvider.cs
- ToolboxSnapDragDropEventArgs.cs
- XPathNavigatorReader.cs
- NavigateEvent.cs
- TcpServerChannel.cs
- XmlSchemaImporter.cs
- OSFeature.cs
- COM2ExtendedBrowsingHandler.cs
- ProtectedConfiguration.cs
- MediaPlayer.cs
- LicenseProviderAttribute.cs
- SendKeys.cs
- LeftCellWrapper.cs
- ObjectContextServiceProvider.cs
- ServiceDesigner.xaml.cs
- LoginView.cs
- DescendentsWalker.cs
- QilParameter.cs
- DropDownList.cs
- WebPartTransformerCollection.cs
- DataRow.cs
- TagNameToTypeMapper.cs
- DynamicDocumentPaginator.cs
- XmlNavigatorStack.cs
- RTTypeWrapper.cs
- PlaceHolder.cs
- DES.cs
- GenericsInstances.cs
- XmlAttributeAttribute.cs
- FlagsAttribute.cs
- FlagsAttribute.cs
- WorkflowQueueInfo.cs
- ObjectView.cs
- FontInfo.cs
- CallContext.cs
- PerformanceCounterScope.cs
- EmptyStringExpandableObjectConverter.cs
- FigureParaClient.cs
- CodeEntryPointMethod.cs
- DataGridViewColumnEventArgs.cs
- ConvertEvent.cs
- AttributeProviderAttribute.cs
- VisualBasicReference.cs
- DataGridRowHeaderAutomationPeer.cs
- GenericXmlSecurityTokenAuthenticator.cs
- DataServiceQueryContinuation.cs
- TemplateBindingExtensionConverter.cs
- SequenceDesigner.cs
- ValidationEventArgs.cs
- SerializerProvider.cs
- SystemWebCachingSectionGroup.cs
- AmbientLight.cs
- TableHeaderCell.cs
- _UriTypeConverter.cs
- Graph.cs
- Stream.cs
- Size.cs
- BufferedGraphicsContext.cs
- ThumbAutomationPeer.cs
- Parameter.cs
- PerformanceCounterPermission.cs
- CommandHelpers.cs
- ClientRolePrincipal.cs
- NetMsmqBindingElement.cs
- XmlSignatureManifest.cs
- SystemIPAddressInformation.cs
- AutomationProperties.cs
- ExpressionWriter.cs
- LocalValueEnumerator.cs
- TextEditorParagraphs.cs
- HttpUnhandledOperationInvoker.cs
- DependencyPropertyValueSerializer.cs