MatrixStack.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / MatrixStack.cs / 1 / MatrixStack.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2001
//
//  File:       MatrixStack.cs 
//-----------------------------------------------------------------------------
 
using System; 
using System.Diagnostics;
using System.Collections; 
using MS.Internal;
using System.Security;
using System.Security.Permissions;
 
namespace System.Windows.Media
{ 
    ///  MatrixStack class implementation 
    internal class MatrixStack
    { 
        private Matrix[] _items;
        private int _size;

#if DEBUG 
        private static readonly int s_initialSize = 4;
#else 
        private static readonly int s_initialSize = 40; // sizeof(Matrix) * 40 =  2240 bytes. Must be > 4 
#endif
        private static readonly int s_growFactor = 2; 
        private static readonly int s_shrinkFactor = s_growFactor + 1;

        // The following members are used to lazily manage the memory allocated by the stack.
        private int _highWaterMark; 
        private int _observeCount;
        private static readonly int s_trimCount = 10; 
 
        public MatrixStack()
        { 
            _items = new Matrix[s_initialSize];
        }

        ///  
        /// Ensures that there is space for at least one more element.
        ///  
        private void EnsureCapacity() 
        {
            // If we reached the capacity of the _items array we need to increase 
            // the size. We use an exponential growth to keep Push in average O(1).
            if (_size == _items.Length)
            {
                Matrix[] newItems = new Matrix[s_growFactor * _size]; 
                Array.Copy(_items, newItems, _size);
                _items = newItems; 
            } 
        }
 
        /// 
        /// Push new matrix on the stack.
        /// 
        /// The new matrix to be pushed 
        /// Iff true, the matrix is multiplied with the current
        /// top matrix on the stack and then pushed on the stack. If false the matrix 
        /// is pushed as is on top of the stack. 
        public void Push(ref Matrix matrix, bool combine)
        { 
            EnsureCapacity();

            if (combine && (_size > 0))
            { 
                // Combine means that we push the product of the top matrix and the new
                // one on the stack. Note that there isn't a top-matrix if the stack is empty. 
                // In this case the top-matrix is assumed to be identity. See else case. 
                _items[_size] = matrix;
 
                // _items[_size] = _items[_size] * _items[_size-1];
                MatrixUtil.MultiplyMatrix(ref _items[_size], ref _items[_size - 1]);
            }
            else 
            {
                // If the stack is empty or we are not combining, we just assign the matrix passed 
                // in to the next free slot in the array. 
                _items[_size] = matrix;
            } 

            _size++;

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this.
            _highWaterMark = Math.Max(_highWaterMark, _size); 
        } 

        ///  
        /// Pushes a transformation on the stack. The transformation is multiplied with the top element
        /// on the stack and then pushed on the stack.
        /// 
        /// 2D transformation. 
        /// The combine argument indicates if the transform should be pushed multiplied with the
        /// current top transform or as is. 
        ///  
        /// The code duplication between Push(ref Matrix, bool) and Push(Transform, bool) is not ideal.
        /// However, we did see a performance gain by optimizing the Push(Transform, bool) method 
        /// minimizing the copies of data.
        /// 
        public void Push(Transform transform, bool combine)
        { 
            EnsureCapacity();
 
            if (combine && (_size > 0)) 
            {
                // Combine means that we push the product of the top matrix and transform 
                // on the stack. Note that there isn't a top-matrix if the stack is empty.
                // In this case the top-matrix is assumed to be identity. See else case.
                // _items[_size] is the new top of the stack, _items[_size - 1] is the
                // previous top. 
                transform.MultiplyValueByMatrix(ref _items[_size], ref _items[_size - 1]);
            } 
            else 
            {
                // If we don't combine or if the stack is empty. 
                _items[_size] = transform.Value;
            }

            _size++; 

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this. 
            _highWaterMark = Math.Max(_highWaterMark, _size);
        } 

        /// 
        /// Pushes the offset on the stack. If the combine flag is true, the offset is applied to the top element before
        /// it is pushed onto the stack. 
        /// 
        public void Push(Vector offset, bool combine) 
        { 
            EnsureCapacity();
 
            if (combine && (_size > 0))
            {
                // In combine mode copy the top element, but only if the stack is not empty.
                _items[_size] = _items[_size-1]; 
            }
            else 
            { 
                // If combine is false, initialize the new top stack element with the identity
                // matrix. 
                _items[_size] = Matrix.Identity;
            }

            // Apply the offset to the new top element. 
            MatrixUtil.PrependOffset(ref _items[_size], offset.X, offset.Y);
 
            _size++; 

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this.
            _highWaterMark = Math.Max(_highWaterMark, _size);
        }
 

        ///  
        /// Pops the top stack element from the stack. 
        /// 
        public void Pop() 
        {
            Debug.Assert(!IsEmpty);
#if DEBUG
            _items[_size-1] = new Matrix(); 
#endif
            _size--; 
        } 

        ///  
        /// Peek returns the matrix on the top of the stack.
        /// 
        public Matrix Peek()
        { 
            Debug.Assert(!IsEmpty);
            return _items[_size-1]; 
        } 

        /// 
        /// This is true iff the stack is empty.
        ///
        public bool IsEmpty { get { return _size == 0; } }
 
        /// 
        /// Instead of allocating and releasing memory continuously while pushing on 
        /// and popping off the stack, we call the optimize method after each frame 
        /// to readjust the internal stack capacity.
        ///  
        public void Optimize()
        {
            Debug.Assert(_size == 0); // The stack must be empty before this is called.
            Debug.Assert(_highWaterMark <= _items.Length); 

            // After s_trimCount calls to this method we check the past usage of the stack. 
            if (_observeCount == s_trimCount) 
            {
                int newSize = Math.Max(_highWaterMark, s_initialSize); 
                if (newSize * (s_shrinkFactor) <= _items.Length)
                {
                    // If the water mark is less or equal to capacity divided by the shrink
                    // factor, then we shrink the stack. Usually the shrink factor is greater 
                    // than the grow factor. This avoids an oscillation of shrinking and growing
                    // the stack if the high water mark goes only slightly up and down. 
 
                    // Note that we don't need to copy the array because the stack is empty.
                    _items = new Matrix[newSize]; 
                }

                _highWaterMark = 0;
                _observeCount = 0; 
            }
            else 
            { 
                // Keep incrementing our observe count
                _observeCount++; 
            }
        }

    } 
}
 
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2001
//
//  File:       MatrixStack.cs 
//-----------------------------------------------------------------------------
 
using System; 
using System.Diagnostics;
using System.Collections; 
using MS.Internal;
using System.Security;
using System.Security.Permissions;
 
namespace System.Windows.Media
{ 
    ///  MatrixStack class implementation 
    internal class MatrixStack
    { 
        private Matrix[] _items;
        private int _size;

#if DEBUG 
        private static readonly int s_initialSize = 4;
#else 
        private static readonly int s_initialSize = 40; // sizeof(Matrix) * 40 =  2240 bytes. Must be > 4 
#endif
        private static readonly int s_growFactor = 2; 
        private static readonly int s_shrinkFactor = s_growFactor + 1;

        // The following members are used to lazily manage the memory allocated by the stack.
        private int _highWaterMark; 
        private int _observeCount;
        private static readonly int s_trimCount = 10; 
 
        public MatrixStack()
        { 
            _items = new Matrix[s_initialSize];
        }

        ///  
        /// Ensures that there is space for at least one more element.
        ///  
        private void EnsureCapacity() 
        {
            // If we reached the capacity of the _items array we need to increase 
            // the size. We use an exponential growth to keep Push in average O(1).
            if (_size == _items.Length)
            {
                Matrix[] newItems = new Matrix[s_growFactor * _size]; 
                Array.Copy(_items, newItems, _size);
                _items = newItems; 
            } 
        }
 
        /// 
        /// Push new matrix on the stack.
        /// 
        /// The new matrix to be pushed 
        /// Iff true, the matrix is multiplied with the current
        /// top matrix on the stack and then pushed on the stack. If false the matrix 
        /// is pushed as is on top of the stack. 
        public void Push(ref Matrix matrix, bool combine)
        { 
            EnsureCapacity();

            if (combine && (_size > 0))
            { 
                // Combine means that we push the product of the top matrix and the new
                // one on the stack. Note that there isn't a top-matrix if the stack is empty. 
                // In this case the top-matrix is assumed to be identity. See else case. 
                _items[_size] = matrix;
 
                // _items[_size] = _items[_size] * _items[_size-1];
                MatrixUtil.MultiplyMatrix(ref _items[_size], ref _items[_size - 1]);
            }
            else 
            {
                // If the stack is empty or we are not combining, we just assign the matrix passed 
                // in to the next free slot in the array. 
                _items[_size] = matrix;
            } 

            _size++;

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this.
            _highWaterMark = Math.Max(_highWaterMark, _size); 
        } 

        ///  
        /// Pushes a transformation on the stack. The transformation is multiplied with the top element
        /// on the stack and then pushed on the stack.
        /// 
        /// 2D transformation. 
        /// The combine argument indicates if the transform should be pushed multiplied with the
        /// current top transform or as is. 
        ///  
        /// The code duplication between Push(ref Matrix, bool) and Push(Transform, bool) is not ideal.
        /// However, we did see a performance gain by optimizing the Push(Transform, bool) method 
        /// minimizing the copies of data.
        /// 
        public void Push(Transform transform, bool combine)
        { 
            EnsureCapacity();
 
            if (combine && (_size > 0)) 
            {
                // Combine means that we push the product of the top matrix and transform 
                // on the stack. Note that there isn't a top-matrix if the stack is empty.
                // In this case the top-matrix is assumed to be identity. See else case.
                // _items[_size] is the new top of the stack, _items[_size - 1] is the
                // previous top. 
                transform.MultiplyValueByMatrix(ref _items[_size], ref _items[_size - 1]);
            } 
            else 
            {
                // If we don't combine or if the stack is empty. 
                _items[_size] = transform.Value;
            }

            _size++; 

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this. 
            _highWaterMark = Math.Max(_highWaterMark, _size);
        } 

        /// 
        /// Pushes the offset on the stack. If the combine flag is true, the offset is applied to the top element before
        /// it is pushed onto the stack. 
        /// 
        public void Push(Vector offset, bool combine) 
        { 
            EnsureCapacity();
 
            if (combine && (_size > 0))
            {
                // In combine mode copy the top element, but only if the stack is not empty.
                _items[_size] = _items[_size-1]; 
            }
            else 
            { 
                // If combine is false, initialize the new top stack element with the identity
                // matrix. 
                _items[_size] = Matrix.Identity;
            }

            // Apply the offset to the new top element. 
            MatrixUtil.PrependOffset(ref _items[_size], offset.X, offset.Y);
 
            _size++; 

            // For memory optimization purposes we track the max usage of the stack here. 
            // See the optimze method for more details about this.
            _highWaterMark = Math.Max(_highWaterMark, _size);
        }
 

        ///  
        /// Pops the top stack element from the stack. 
        /// 
        public void Pop() 
        {
            Debug.Assert(!IsEmpty);
#if DEBUG
            _items[_size-1] = new Matrix(); 
#endif
            _size--; 
        } 

        ///  
        /// Peek returns the matrix on the top of the stack.
        /// 
        public Matrix Peek()
        { 
            Debug.Assert(!IsEmpty);
            return _items[_size-1]; 
        } 

        /// 
        /// This is true iff the stack is empty.
        ///
        public bool IsEmpty { get { return _size == 0; } }
 
        /// 
        /// Instead of allocating and releasing memory continuously while pushing on 
        /// and popping off the stack, we call the optimize method after each frame 
        /// to readjust the internal stack capacity.
        ///  
        public void Optimize()
        {
            Debug.Assert(_size == 0); // The stack must be empty before this is called.
            Debug.Assert(_highWaterMark <= _items.Length); 

            // After s_trimCount calls to this method we check the past usage of the stack. 
            if (_observeCount == s_trimCount) 
            {
                int newSize = Math.Max(_highWaterMark, s_initialSize); 
                if (newSize * (s_shrinkFactor) <= _items.Length)
                {
                    // If the water mark is less or equal to capacity divided by the shrink
                    // factor, then we shrink the stack. Usually the shrink factor is greater 
                    // than the grow factor. This avoids an oscillation of shrinking and growing
                    // the stack if the high water mark goes only slightly up and down. 
 
                    // Note that we don't need to copy the array because the stack is empty.
                    _items = new Matrix[newSize]; 
                }

                _highWaterMark = 0;
                _observeCount = 0; 
            }
            else 
            { 
                // Keep incrementing our observe count
                _observeCount++; 
            }
        }

    } 
}
 
 

// 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