BitmapEffectState.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / Effects / BitmapEffectState.cs / 1 / BitmapEffectState.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// File: BitmapEffectState.cs 
//
// Description: This file contains the implementation of BitmapEffectState. 
//              This is the base class for holding the bitmap effect state. 
//
// History: 
//  07/25/2005 : [....] - Created it.
//
//---------------------------------------------------------------------------
using System; 
using System.Windows.Threading;
 
using MS.Win32; 
using System.Security;
using System.Security.Permissions; 
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging; 
using System.Diagnostics;
using System.Collections; 
using System.Collections.Generic; 
using MS.Internal;
using System.Resources; 
using MS.Utility;
using System.Runtime.InteropServices;
using MS.Internal.PresentationCore;
 
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID; 
 
namespace System.Windows.Media.Effects
{ 
    internal class BitmapEffectState
    {
        public BitmapEffectState()
        { 

        } 
 
        internal BitmapEffect BitmapEffect
        { 
            get { return _bitmapEffect; }
            set { _bitmapEffect = value; }
        }
 
        internal BitmapEffectInput BitmapEffectInput
        { 
            get { return _bitmapEffectInput; } 
            set { _bitmapEffectInput = value; }
        } 

        /// 
        /// Calculates the bitmap effect bounds given a bounding box
        ///  
        /// 
        ///  
        internal Rect GetBounds(Rect bbox) 
        {
            if (_bitmapEffect == null) 
            {
                return bbox;
            }
 
            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ?
                                                   _bitmapEffectInput : 
                                                   new BitmapEffectInput(); 

            return _bitmapEffect.TransformRect(bitmapEffectInput, bbox, false /* fInverse */); 
        }

        /// 
        /// Transforms a point for hit testing 
        /// 
        ///  
        ///  
        /// 
        ///  
        internal bool TransformHitPoint(Rect bounds, Point inPoint, out Point outPoint)
        {
            outPoint = inPoint;
            if (_bitmapEffect == null) 
            {
                return false; 
            } 

            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ? 
                                                   _bitmapEffectInput :
                                                   new BitmapEffectInput();
            _bitmapEffect.VisualBounds = bounds;
            return _bitmapEffect.TransformPoint(bitmapEffectInput, inPoint, out outPoint, true); 
        }
 
        ///  
        /// This method extracts the scale matrix out of the matrix passed in
        ///  
        /// the matrix to decompose
        /// the scale matrix
        private Matrix ExtractScaleMatrix(Matrix matrix)
        { 
            Vector transformedUnitX = matrix.Transform(new Vector(1.0, 0.0));
            Vector transformedUnitY = matrix.Transform(new Vector(0.0, 1.0)); 
 
            return Matrix.CreateScaling(
                transformedUnitX.Length, 
                transformedUnitY.Length);
        }

        ///  
        /// This methods renders the visual to a bitmap, then applies
        /// the effect to the rendered bitmap, and sets the content 
        /// of the visual to be the resulting bitmap 
        /// 
        ///  
        /// SecurityCritical: This is code that retrieves the WicSourceHandle which is critical
        /// SecurityTreatAsSafe: The inputs are safe and WicSourceHandle is not given out.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected BitmapSource GetEffectOutput(Visual visual, ref RenderTargetBitmap renderBitmap, Matrix worldTransform, Rect windowClip, out Matrix finalTransform)
        { 
            BitmapSource outputImage = null; 
            finalTransform = worldTransform;
 
            if (worldTransform.HasInverse)
            {
                // Compute the bounding box of the visual and its descendants
                // NOTE: PushEffect could have empty bounds if there is nothing 
                // drawn between the PushEffect and Pop calls
                Rect bounds = visual.VisualContentBounds; 
                bounds.Union(visual.VisualDescendantBounds); 

                Matrix scaleMatrix = ExtractScaleMatrix(worldTransform); 
                Matrix effectMatrix = scaleMatrix;
                effectMatrix.OffsetX = worldTransform.OffsetX;
                effectMatrix.OffsetY = worldTransform.OffsetY;
 
                // this is to handle RTL scenarios
                Matrix flipMatrix = Matrix.CreateScaling(worldTransform.M11 / Math.Abs(worldTransform.M11), 
                                                         worldTransform.M22 / Math.Abs(worldTransform.M22)); 

                if (!flipMatrix.IsIdentity) 
                    bounds.Transform(flipMatrix);

                // apply the scale transform to the bounds
                bounds.Transform(effectMatrix); 

                // clip to the size of the screen + windowClip 
                bounds.Intersect(GetClipRect(windowClip)); 

                if (!flipMatrix.IsIdentity) 
                    bounds.Transform(flipMatrix);

                if (!bounds.IsEmpty)
                { 
                    // round to the nearest integer
                    // we want to make sure everything is pixel aligned otherwise we 
                    // potentially get blurring, see bug 1245106 
                    bounds.Width = Math.Ceiling(bounds.Right) - Math.Floor(bounds.Left);
                    bounds.Height = Math.Ceiling(bounds.Bottom) - Math.Floor(bounds.Top); 
                    bounds.X = Math.Floor(bounds.X);
                    bounds.Y = Math.Floor(bounds.Y);

                    // start drawing at 0,0 
                    effectMatrix.Translate(-bounds.X*flipMatrix.M11, -bounds.Y*flipMatrix.M22);
 
                    int width = (int)bounds.Width; 
                    int height = (int)bounds.Height;
 
                    // if the bounds have either 0 height or 0 width,
                    // we don't want to render anything
                    // This is because you cannot create an empty image.
                    if (width > 0 && height > 0) 
                    {
                        if (renderBitmap == null || 
                            renderBitmap.PixelWidth != width || 
                            renderBitmap.PixelHeight != height)
                        { 

                            renderBitmap = new RenderTargetBitmap(width,
                                                                  height,
                                                                  DefaultDevicePixelsPerInch, 
                                                                  DefaultDevicePixelsPerInch,
                                                                  PixelFormats.Pbgra32); 
                        } 

                        renderBitmap.RenderForBitmapEffect(visual, effectMatrix, windowClip); 

                        if (_bitmapEffect != null)
                        {
                            // Push our worldTransform into the render context. This will make an interop 
                            // call into the unmanaged render context object.
                            _bitmapEffect.RenderContext.Transform = worldTransform; 
 
                            // set up the input
                            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ? 
                                                                   _bitmapEffectInput :
                                                                   new BitmapEffectInput();

                            if (bitmapEffectInput.Input == BitmapEffectInput.ContextInputSource || 
                                bitmapEffectInput.Input == null)
                            { 
                                bitmapEffectInput = bitmapEffectInput.CloneCurrentValue(); 
                                bitmapEffectInput.Input = renderBitmap;
                            } 
                            else if (scaleMatrix.IsIdentity == false)
                            {
                                bitmapEffectInput.Input = new TransformedBitmap(bitmapEffectInput.Input, new MatrixTransform(scaleMatrix));
                            } 

 
                            if (bitmapEffectInput.AreaToApplyEffectUnits == BrushMappingMode.Absolute) 
                            {
                                Rect area = bitmapEffectInput.AreaToApplyEffect; 
                                area.Transform(scaleMatrix);
                                bitmapEffectInput.AreaToApplyEffect = area;
                            }
 
                            // Run the effect
                            outputImage = _bitmapEffect.GetOutput(bitmapEffectInput); 
 
                            // Get back our final transformation (i.e. the one the effect graph
                            // updated, since it may have offset the output image). 
                            finalTransform = _bitmapEffect.RenderContext.Transform;
                        }
                        else
                        { 
                            outputImage = new UnmanagedBitmapWrapper(renderBitmap.WicSourceHandle);
                            finalTransform = Matrix.Identity; 
                        } 

                        // transform back the image, because the world transform will 
                        // be applied to the visual again
                        //
                        // This is equivalent to - EffectOffset*BoundsOffset*WorldInverse
                        // EffectOffset is the potential offset needed if an effect expands the 
                        // bounds
                        // BoundsOffset is to draw the image where necessary since we translated it 
                        // to be drawn at (0,0) 
                        // WorldInverse is necessary since we already applied the world transform
 
                        effectMatrix.Invert();
                        finalTransform = Matrix.CreateTranslation(finalTransform._offsetX, finalTransform._offsetY) * effectMatrix;
                    }
                } 

            } 
            return outputImage; 
        }
 
        /// 
        /// SecurityCritical: This is code that calls into native unmanaged methods
        /// SecurityTreatAsSafe: This data is not unsecure and the elevation has a SUC on it.
        ///  
        private static Rect ScreenRect
        { 
 
        [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                if (_screenRect.IsEmpty)
                {
                    _screenRect = new Rect( 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_XVIRTUALSCREEN),
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_YVIRTUALSCREEN), 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CXVIRTUALSCREEN), 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CYVIRTUALSCREEN));
 
                }

                return _screenRect;
            } 
        }
 
        ///  
        /// Computes the window clip used to clip the visual bounds against
        ///  
        private Rect GetClipRect(Rect rect)
        {
            Rect clipRect = BitmapEffectState.ScreenRect;
            clipRect.Union(rect); 
            clipRect.X -= WindowClipPadding;
            clipRect.Y -= WindowClipPadding; 
            clipRect.Width += WindowClipPadding; 
            clipRect.Height += WindowClipPadding;
 
            return clipRect;
        }

 
        #region Fields
 
        protected BitmapEffect _bitmapEffect; 
        protected BitmapEffectInput _bitmapEffectInput;
        protected static Rect _screenRect = Rect.Empty; 
        private const int WindowClipPadding = 100;

        internal const double DefaultDevicePixelsPerInch = 96.0;
 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// File: BitmapEffectState.cs 
//
// Description: This file contains the implementation of BitmapEffectState. 
//              This is the base class for holding the bitmap effect state. 
//
// History: 
//  07/25/2005 : [....] - Created it.
//
//---------------------------------------------------------------------------
using System; 
using System.Windows.Threading;
 
using MS.Win32; 
using System.Security;
using System.Security.Permissions; 
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging; 
using System.Diagnostics;
using System.Collections; 
using System.Collections.Generic; 
using MS.Internal;
using System.Resources; 
using MS.Utility;
using System.Runtime.InteropServices;
using MS.Internal.PresentationCore;
 
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID; 
 
namespace System.Windows.Media.Effects
{ 
    internal class BitmapEffectState
    {
        public BitmapEffectState()
        { 

        } 
 
        internal BitmapEffect BitmapEffect
        { 
            get { return _bitmapEffect; }
            set { _bitmapEffect = value; }
        }
 
        internal BitmapEffectInput BitmapEffectInput
        { 
            get { return _bitmapEffectInput; } 
            set { _bitmapEffectInput = value; }
        } 

        /// 
        /// Calculates the bitmap effect bounds given a bounding box
        ///  
        /// 
        ///  
        internal Rect GetBounds(Rect bbox) 
        {
            if (_bitmapEffect == null) 
            {
                return bbox;
            }
 
            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ?
                                                   _bitmapEffectInput : 
                                                   new BitmapEffectInput(); 

            return _bitmapEffect.TransformRect(bitmapEffectInput, bbox, false /* fInverse */); 
        }

        /// 
        /// Transforms a point for hit testing 
        /// 
        ///  
        ///  
        /// 
        ///  
        internal bool TransformHitPoint(Rect bounds, Point inPoint, out Point outPoint)
        {
            outPoint = inPoint;
            if (_bitmapEffect == null) 
            {
                return false; 
            } 

            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ? 
                                                   _bitmapEffectInput :
                                                   new BitmapEffectInput();
            _bitmapEffect.VisualBounds = bounds;
            return _bitmapEffect.TransformPoint(bitmapEffectInput, inPoint, out outPoint, true); 
        }
 
        ///  
        /// This method extracts the scale matrix out of the matrix passed in
        ///  
        /// the matrix to decompose
        /// the scale matrix
        private Matrix ExtractScaleMatrix(Matrix matrix)
        { 
            Vector transformedUnitX = matrix.Transform(new Vector(1.0, 0.0));
            Vector transformedUnitY = matrix.Transform(new Vector(0.0, 1.0)); 
 
            return Matrix.CreateScaling(
                transformedUnitX.Length, 
                transformedUnitY.Length);
        }

        ///  
        /// This methods renders the visual to a bitmap, then applies
        /// the effect to the rendered bitmap, and sets the content 
        /// of the visual to be the resulting bitmap 
        /// 
        ///  
        /// SecurityCritical: This is code that retrieves the WicSourceHandle which is critical
        /// SecurityTreatAsSafe: The inputs are safe and WicSourceHandle is not given out.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected BitmapSource GetEffectOutput(Visual visual, ref RenderTargetBitmap renderBitmap, Matrix worldTransform, Rect windowClip, out Matrix finalTransform)
        { 
            BitmapSource outputImage = null; 
            finalTransform = worldTransform;
 
            if (worldTransform.HasInverse)
            {
                // Compute the bounding box of the visual and its descendants
                // NOTE: PushEffect could have empty bounds if there is nothing 
                // drawn between the PushEffect and Pop calls
                Rect bounds = visual.VisualContentBounds; 
                bounds.Union(visual.VisualDescendantBounds); 

                Matrix scaleMatrix = ExtractScaleMatrix(worldTransform); 
                Matrix effectMatrix = scaleMatrix;
                effectMatrix.OffsetX = worldTransform.OffsetX;
                effectMatrix.OffsetY = worldTransform.OffsetY;
 
                // this is to handle RTL scenarios
                Matrix flipMatrix = Matrix.CreateScaling(worldTransform.M11 / Math.Abs(worldTransform.M11), 
                                                         worldTransform.M22 / Math.Abs(worldTransform.M22)); 

                if (!flipMatrix.IsIdentity) 
                    bounds.Transform(flipMatrix);

                // apply the scale transform to the bounds
                bounds.Transform(effectMatrix); 

                // clip to the size of the screen + windowClip 
                bounds.Intersect(GetClipRect(windowClip)); 

                if (!flipMatrix.IsIdentity) 
                    bounds.Transform(flipMatrix);

                if (!bounds.IsEmpty)
                { 
                    // round to the nearest integer
                    // we want to make sure everything is pixel aligned otherwise we 
                    // potentially get blurring, see bug 1245106 
                    bounds.Width = Math.Ceiling(bounds.Right) - Math.Floor(bounds.Left);
                    bounds.Height = Math.Ceiling(bounds.Bottom) - Math.Floor(bounds.Top); 
                    bounds.X = Math.Floor(bounds.X);
                    bounds.Y = Math.Floor(bounds.Y);

                    // start drawing at 0,0 
                    effectMatrix.Translate(-bounds.X*flipMatrix.M11, -bounds.Y*flipMatrix.M22);
 
                    int width = (int)bounds.Width; 
                    int height = (int)bounds.Height;
 
                    // if the bounds have either 0 height or 0 width,
                    // we don't want to render anything
                    // This is because you cannot create an empty image.
                    if (width > 0 && height > 0) 
                    {
                        if (renderBitmap == null || 
                            renderBitmap.PixelWidth != width || 
                            renderBitmap.PixelHeight != height)
                        { 

                            renderBitmap = new RenderTargetBitmap(width,
                                                                  height,
                                                                  DefaultDevicePixelsPerInch, 
                                                                  DefaultDevicePixelsPerInch,
                                                                  PixelFormats.Pbgra32); 
                        } 

                        renderBitmap.RenderForBitmapEffect(visual, effectMatrix, windowClip); 

                        if (_bitmapEffect != null)
                        {
                            // Push our worldTransform into the render context. This will make an interop 
                            // call into the unmanaged render context object.
                            _bitmapEffect.RenderContext.Transform = worldTransform; 
 
                            // set up the input
                            BitmapEffectInput bitmapEffectInput = (_bitmapEffectInput != null) ? 
                                                                   _bitmapEffectInput :
                                                                   new BitmapEffectInput();

                            if (bitmapEffectInput.Input == BitmapEffectInput.ContextInputSource || 
                                bitmapEffectInput.Input == null)
                            { 
                                bitmapEffectInput = bitmapEffectInput.CloneCurrentValue(); 
                                bitmapEffectInput.Input = renderBitmap;
                            } 
                            else if (scaleMatrix.IsIdentity == false)
                            {
                                bitmapEffectInput.Input = new TransformedBitmap(bitmapEffectInput.Input, new MatrixTransform(scaleMatrix));
                            } 

 
                            if (bitmapEffectInput.AreaToApplyEffectUnits == BrushMappingMode.Absolute) 
                            {
                                Rect area = bitmapEffectInput.AreaToApplyEffect; 
                                area.Transform(scaleMatrix);
                                bitmapEffectInput.AreaToApplyEffect = area;
                            }
 
                            // Run the effect
                            outputImage = _bitmapEffect.GetOutput(bitmapEffectInput); 
 
                            // Get back our final transformation (i.e. the one the effect graph
                            // updated, since it may have offset the output image). 
                            finalTransform = _bitmapEffect.RenderContext.Transform;
                        }
                        else
                        { 
                            outputImage = new UnmanagedBitmapWrapper(renderBitmap.WicSourceHandle);
                            finalTransform = Matrix.Identity; 
                        } 

                        // transform back the image, because the world transform will 
                        // be applied to the visual again
                        //
                        // This is equivalent to - EffectOffset*BoundsOffset*WorldInverse
                        // EffectOffset is the potential offset needed if an effect expands the 
                        // bounds
                        // BoundsOffset is to draw the image where necessary since we translated it 
                        // to be drawn at (0,0) 
                        // WorldInverse is necessary since we already applied the world transform
 
                        effectMatrix.Invert();
                        finalTransform = Matrix.CreateTranslation(finalTransform._offsetX, finalTransform._offsetY) * effectMatrix;
                    }
                } 

            } 
            return outputImage; 
        }
 
        /// 
        /// SecurityCritical: This is code that calls into native unmanaged methods
        /// SecurityTreatAsSafe: This data is not unsecure and the elevation has a SUC on it.
        ///  
        private static Rect ScreenRect
        { 
 
        [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                if (_screenRect.IsEmpty)
                {
                    _screenRect = new Rect( 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_XVIRTUALSCREEN),
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_YVIRTUALSCREEN), 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CXVIRTUALSCREEN), 
                        UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CYVIRTUALSCREEN));
 
                }

                return _screenRect;
            } 
        }
 
        ///  
        /// Computes the window clip used to clip the visual bounds against
        ///  
        private Rect GetClipRect(Rect rect)
        {
            Rect clipRect = BitmapEffectState.ScreenRect;
            clipRect.Union(rect); 
            clipRect.X -= WindowClipPadding;
            clipRect.Y -= WindowClipPadding; 
            clipRect.Width += WindowClipPadding; 
            clipRect.Height += WindowClipPadding;
 
            return clipRect;
        }

 
        #region Fields
 
        protected BitmapEffect _bitmapEffect; 
        protected BitmapEffectInput _bitmapEffectInput;
        protected static Rect _screenRect = Rect.Empty; 
        private const int WindowClipPadding = 100;

        internal const double DefaultDevicePixelsPerInch = 96.0;
 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK