| File: System\Windows\Media\Imaging\BitmapVisualManager.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationCore\PresentationCore.csproj (PresentationCore) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Windows.Threading; using MS.Internal; using System.Windows.Media.Composition; using MS.Win32.PresentationCore; namespace System.Windows.Media.Imaging { #region public class BitmapVisualManager /// <summary> /// BitmapVisualManager holds state and context for a drawing a visual to an bitmap. /// </summary> internal class BitmapVisualManager : DispatcherObject { #region Constructors private BitmapVisualManager() { } /// <summary> /// Create an BitmapVisualManager for drawing a visual to the bitmap. /// </summary> /// <param name="bitmapTarget">Where the resulting bitmap is rendered</param> public BitmapVisualManager(RenderTargetBitmap bitmapTarget) { ArgumentNullException.ThrowIfNull(bitmapTarget); if (bitmapTarget.IsFrozen) { throw new ArgumentException(SR.Format(SR.Image_CantBeFrozen, null)); } _bitmapTarget = bitmapTarget; } #endregion #region Public methods /// <summary> /// Render visual to printer. /// </summary> /// <param name="visual">Root of the visual to render</param> public void Render(Visual visual) { Render(visual, Matrix.Identity, Rect.Empty); } /// <summary> /// Render visual to printer. /// </summary> /// <param name="visual">Root of the visual to render</param> /// <param name="worldTransform">World transform to apply to the root visual</param> /// <param name="windowClip">The window clip of the outermost window or Empty</param> /// <param name="fRenderForBitmapEffect">True if we are rendering the visual /// to apply an effect to it</param> /// internal void Render(Visual visual, Matrix worldTransform, Rect windowClip) { ArgumentNullException.ThrowIfNull(visual); // If the bitmapTarget we're writing to is frozen then we can't proceed. Note that // it's possible for the BitmapVisualManager to be constructed with a mutable BitmapImage // and for the app to later freeze it. Such an application is misbehaving if // they subsequently try to render to the BitmapImage. if (_bitmapTarget.IsFrozen) { throw new ArgumentException(SR.Image_CantBeFrozen); } int sizeX = _bitmapTarget.PixelWidth; int sizeY = _bitmapTarget.PixelHeight; double dpiX = _bitmapTarget.DpiX; double dpiY = _bitmapTarget.DpiY; Debug.Assert ((sizeX > 0) && (sizeY > 0)); Debug.Assert ((dpiX > 0) && (dpiY > 0)); // validate the data if ((sizeX <= 0) || (sizeY <= 0)) { return; // nothing to draw } if ((dpiX <= 0) || (dpiY <= 0)) { dpiX = 96; dpiY = 96; } SafeMILHandle renderTargetBitmap = _bitmapTarget.MILRenderTarget; Debug.Assert (renderTargetBitmap != null, "Render Target is null"); IntPtr pIRenderTargetBitmap = IntPtr.Zero; try { // // Allocate a fresh synchronous channel. // MediaContext mctx = MediaContext.CurrentMediaContext; DUCE.Channel channel = mctx.AllocateSyncChannel(); // // Acquire the target bitmap. // Guid iidRTB = MILGuidData.IID_IMILRenderTargetBitmap; HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface( renderTargetBitmap, ref iidRTB, out pIRenderTargetBitmap)); // // Render the visual on the synchronous channel. // Renderer.Render( pIRenderTargetBitmap, channel, visual, sizeX, sizeY, dpiX, dpiY, worldTransform, windowClip); // // Release the synchronous channel. This way we can // re-use that channel later. // mctx.ReleaseSyncChannel(channel); } finally { UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref pIRenderTargetBitmap); } _bitmapTarget.RenderTargetContentsChanged(); } #endregion #region Member Variables private RenderTargetBitmap _bitmapTarget = null; #endregion } #endregion }