GeometryHitTestParameters.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 / GeometryHitTestParameters.cs / 1 / GeometryHitTestParameters.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File:       GeometryHitTestParameters 
//-----------------------------------------------------------------------------
 
using System; 
using System.Windows.Media;
using System.Windows.Media.Animation; 
using System.Windows.Threading;
using System.Security;
using System.Security.Permissions;
 
using System.Collections;
using System.Diagnostics; 
using MS.Internal; 

namespace System.Windows.Media 
{
    /// 
    /// This is the class for specifying parameters hit testing with a geometry.
    ///  
    public class GeometryHitTestParameters : HitTestParameters
    { 
        private PathGeometry _hitGeometryInternal;  // The internal geometry we use for hit testing 
        private Geometry _hitGeometryCache = null;  // Cached frozen copy we hand out from HitGeometry property.
        private Rect _origBounds; 
        private Rect _bounds;
        private MatrixStack _matrixStack;

        ///  
        /// The constructor takes the geometry to hit test with.
        ///  
        public GeometryHitTestParameters(Geometry geometry) : base() 
        {
            // This ctor guarantees that we are initialized in the following way: 
            //
            //  1.  The geometry provided by the user is unmodified
            //  2.  _hitGeometryInternal is a PathGeometry equivilent to the supplied geometry
            //  3.  _hitGeometryInternal.Tranform is a MatrixTransform equivilent to the supplied 
            //      geometry.Transform
            //  4.  _origBounds is the untransformed bounds of the _hitGeometryInternal (inner space). 
            //  5.  _bounds is the transformed bounds of the _hitGeometryInternal (outer space). 
            //  6.  _matrixStack is an empty stack.
 
            if (geometry == null)
            {
                throw new ArgumentNullException("geometry");
            } 

            // Convert the Geometry to an equivilent PathGeometry up front to prevent 
            // conversion on every call to DoesContainWithDetail.  If the geometry is 
            // animate this also has the side effect of eliminating animation interplay.
            _hitGeometryInternal = geometry.GetAsPathGeometry(); 

            // If GetAsPathGeometry was a no-op, force the copy because we do not
            // went to modify the user's Geometry.
            if (object.ReferenceEquals(_hitGeometryInternal, geometry)) 
            {
                _hitGeometryInternal = _hitGeometryInternal.Clone(); 
            } 

            // Convert _hitGeometryInternal.Transform to an equivilent MatrixTransform 
            // so that we can aggregate in PushMatrix/PopMatrix without building a
            // TransformCollection.
            Transform origTransform = _hitGeometryInternal.Transform;
            MatrixTransform newTransform = new MatrixTransform(); 

            _hitGeometryInternal.Transform = newTransform; 
 
            // Before we initialize MatrixTransform.Matrix, cache the bounds of this
            // geometry without any transforms. 
            _origBounds = _hitGeometryInternal.Bounds;

            // If we had a non-Identity transform, update our MatrixTransform.Matrix
            // with its Value.  (Note that when GetAsPathGeometry *isn't* a no-op 
            // it applies the transform to the figures and returns with a Geometry
            // with an identity Transform.) 
            if (origTransform != null && !origTransform.IsIdentity) 
            {
                newTransform.Matrix = origTransform.Value; 
            }

            // Initialize the current transformed bounds of this Geometry
            _bounds = _hitGeometryInternal.Bounds; 
            _matrixStack = new MatrixStack();
        } 
 
        /// 
        /// The geometry to hit test against.  This will be a frozen copy of the 
        /// hit geometry transformed into the local space of the Visual being hit
        /// tested.
        /// 
        public Geometry HitGeometry 
        {
            get 
            { 
                if (_hitGeometryCache == null)
                { 
                    _hitGeometryCache = (Geometry) _hitGeometryInternal.GetAsFrozen();
                }

                Debug.Assert(_hitGeometryInternal.Transform.Value == _hitGeometryCache.Transform.Value, 
                    "HitGeometry has a different transform than HitGeometryInternal. Did we forget to invalidate the cache?");
 
                return _hitGeometryCache; 
            }
        } 

        // Use this property when retrieving the hit geometry internally.  Right now it avoids a
        // a cast.  In the future it will avoid a copy as well (see bug 1133159).  The value from
        // this property should never be exposed to the user (e.g., do not use it to return 
        // hit test results.)
        internal PathGeometry InternalHitGeometry 
        { 
            get
            { 
                return _hitGeometryInternal;
            }
        }
 
        internal Rect Bounds
        { 
            get 
            {
                return _bounds; 
            }
        }

        internal void PushMatrix(ref Matrix newMatrix) 
        {
            MatrixTransform matrixTransform = (MatrixTransform) _hitGeometryInternal.Transform; 
 
            // Grab the old composedMatrix from our MatrixTransform and save
            // it on our MatrixStack. 
            Matrix composedMatrix = matrixTransform.Value;
            _matrixStack.Push(ref composedMatrix, false);

            // Compose the new matrix into our MatrixTransform 
            MatrixUtil.MultiplyMatrix(ref composedMatrix, ref newMatrix);
 
            matrixTransform.Matrix = composedMatrix; 

            // Update active bounds based on new tranform. 
            _bounds = Rect.Transform(_origBounds, composedMatrix);

            ClearHitGeometryCache();
        } 

        internal void PopMatrix() 
        { 
            Matrix matrix = _matrixStack.Peek();
 
            // Restore saved transform.
            ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix = matrix;

            // Update active bounds based on new X-form. 
            _bounds = Rect.Transform(_origBounds, matrix);
 
            _matrixStack.Pop(); 

            ClearHitGeometryCache(); 
        }

        // This method is called to restore the _hitGeometryInternal's transform to its original state
        // in the event that a user's delegate threw an exception during the hit test walk. 
        internal void EmergencyRestoreOriginalTransform()
        { 
            // Replace the current transform with the first matrix pushed onto the stack. 
            Matrix matrix = ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix;
 
            while (!_matrixStack.IsEmpty)
            {
                matrix = _matrixStack.Peek();
                _matrixStack.Pop(); 
            }
 
            ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix = matrix; 

            ClearHitGeometryCache(); 
        }

        // This clears the
        private void ClearHitGeometryCache() 
        {
            _hitGeometryCache = null; 
        } 
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File:       GeometryHitTestParameters 
//-----------------------------------------------------------------------------
 
using System; 
using System.Windows.Media;
using System.Windows.Media.Animation; 
using System.Windows.Threading;
using System.Security;
using System.Security.Permissions;
 
using System.Collections;
using System.Diagnostics; 
using MS.Internal; 

namespace System.Windows.Media 
{
    /// 
    /// This is the class for specifying parameters hit testing with a geometry.
    ///  
    public class GeometryHitTestParameters : HitTestParameters
    { 
        private PathGeometry _hitGeometryInternal;  // The internal geometry we use for hit testing 
        private Geometry _hitGeometryCache = null;  // Cached frozen copy we hand out from HitGeometry property.
        private Rect _origBounds; 
        private Rect _bounds;
        private MatrixStack _matrixStack;

        ///  
        /// The constructor takes the geometry to hit test with.
        ///  
        public GeometryHitTestParameters(Geometry geometry) : base() 
        {
            // This ctor guarantees that we are initialized in the following way: 
            //
            //  1.  The geometry provided by the user is unmodified
            //  2.  _hitGeometryInternal is a PathGeometry equivilent to the supplied geometry
            //  3.  _hitGeometryInternal.Tranform is a MatrixTransform equivilent to the supplied 
            //      geometry.Transform
            //  4.  _origBounds is the untransformed bounds of the _hitGeometryInternal (inner space). 
            //  5.  _bounds is the transformed bounds of the _hitGeometryInternal (outer space). 
            //  6.  _matrixStack is an empty stack.
 
            if (geometry == null)
            {
                throw new ArgumentNullException("geometry");
            } 

            // Convert the Geometry to an equivilent PathGeometry up front to prevent 
            // conversion on every call to DoesContainWithDetail.  If the geometry is 
            // animate this also has the side effect of eliminating animation interplay.
            _hitGeometryInternal = geometry.GetAsPathGeometry(); 

            // If GetAsPathGeometry was a no-op, force the copy because we do not
            // went to modify the user's Geometry.
            if (object.ReferenceEquals(_hitGeometryInternal, geometry)) 
            {
                _hitGeometryInternal = _hitGeometryInternal.Clone(); 
            } 

            // Convert _hitGeometryInternal.Transform to an equivilent MatrixTransform 
            // so that we can aggregate in PushMatrix/PopMatrix without building a
            // TransformCollection.
            Transform origTransform = _hitGeometryInternal.Transform;
            MatrixTransform newTransform = new MatrixTransform(); 

            _hitGeometryInternal.Transform = newTransform; 
 
            // Before we initialize MatrixTransform.Matrix, cache the bounds of this
            // geometry without any transforms. 
            _origBounds = _hitGeometryInternal.Bounds;

            // If we had a non-Identity transform, update our MatrixTransform.Matrix
            // with its Value.  (Note that when GetAsPathGeometry *isn't* a no-op 
            // it applies the transform to the figures and returns with a Geometry
            // with an identity Transform.) 
            if (origTransform != null && !origTransform.IsIdentity) 
            {
                newTransform.Matrix = origTransform.Value; 
            }

            // Initialize the current transformed bounds of this Geometry
            _bounds = _hitGeometryInternal.Bounds; 
            _matrixStack = new MatrixStack();
        } 
 
        /// 
        /// The geometry to hit test against.  This will be a frozen copy of the 
        /// hit geometry transformed into the local space of the Visual being hit
        /// tested.
        /// 
        public Geometry HitGeometry 
        {
            get 
            { 
                if (_hitGeometryCache == null)
                { 
                    _hitGeometryCache = (Geometry) _hitGeometryInternal.GetAsFrozen();
                }

                Debug.Assert(_hitGeometryInternal.Transform.Value == _hitGeometryCache.Transform.Value, 
                    "HitGeometry has a different transform than HitGeometryInternal. Did we forget to invalidate the cache?");
 
                return _hitGeometryCache; 
            }
        } 

        // Use this property when retrieving the hit geometry internally.  Right now it avoids a
        // a cast.  In the future it will avoid a copy as well (see bug 1133159).  The value from
        // this property should never be exposed to the user (e.g., do not use it to return 
        // hit test results.)
        internal PathGeometry InternalHitGeometry 
        { 
            get
            { 
                return _hitGeometryInternal;
            }
        }
 
        internal Rect Bounds
        { 
            get 
            {
                return _bounds; 
            }
        }

        internal void PushMatrix(ref Matrix newMatrix) 
        {
            MatrixTransform matrixTransform = (MatrixTransform) _hitGeometryInternal.Transform; 
 
            // Grab the old composedMatrix from our MatrixTransform and save
            // it on our MatrixStack. 
            Matrix composedMatrix = matrixTransform.Value;
            _matrixStack.Push(ref composedMatrix, false);

            // Compose the new matrix into our MatrixTransform 
            MatrixUtil.MultiplyMatrix(ref composedMatrix, ref newMatrix);
 
            matrixTransform.Matrix = composedMatrix; 

            // Update active bounds based on new tranform. 
            _bounds = Rect.Transform(_origBounds, composedMatrix);

            ClearHitGeometryCache();
        } 

        internal void PopMatrix() 
        { 
            Matrix matrix = _matrixStack.Peek();
 
            // Restore saved transform.
            ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix = matrix;

            // Update active bounds based on new X-form. 
            _bounds = Rect.Transform(_origBounds, matrix);
 
            _matrixStack.Pop(); 

            ClearHitGeometryCache(); 
        }

        // This method is called to restore the _hitGeometryInternal's transform to its original state
        // in the event that a user's delegate threw an exception during the hit test walk. 
        internal void EmergencyRestoreOriginalTransform()
        { 
            // Replace the current transform with the first matrix pushed onto the stack. 
            Matrix matrix = ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix;
 
            while (!_matrixStack.IsEmpty)
            {
                matrix = _matrixStack.Peek();
                _matrixStack.Pop(); 
            }
 
            ((MatrixTransform) (_hitGeometryInternal.Transform)).Matrix = matrix; 

            ClearHitGeometryCache(); 
        }

        // This clears the
        private void ClearHitGeometryCache() 
        {
            _hitGeometryCache = null; 
        } 
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

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