StylusPoint.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 / Input / Stylus / StylusPoint.cs / 1 / StylusPoint.cs

                            //------------------------------------------------------------------------ 
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
//----------------------------------------------------------------------- 

using System; 
using System.Windows; 
using System.Diagnostics;
using System.Windows.Input; 
using System.Windows.Media;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using MS.Utility; 
using MS.Internal;
using SR = MS.Internal.PresentationCore.SR; 
using SRID = MS.Internal.PresentationCore.SRID; 

namespace System.Windows.Input 
{
    /// 
    /// Represents a single sampling point from a stylus input device
    ///  
    public struct StylusPoint : IEquatable
    { 
        internal static readonly float DefaultPressure = 0.5f; 

 
        private double _x;
        private double _y;
        private float _pressureFactor;
        private int[] _additionalValues; 
        private StylusPointDescription _stylusPointDescription;
 
        #region Constructors 
        /// 
        /// StylusPoint 
        /// 
        /// x
        /// y
        public StylusPoint(double x, double y) 
            : this(x, y, DefaultPressure, null, null, false, false)
        { 
        } 

        ///  
        /// StylusPoint
        /// 
        /// x
        /// y 
        /// pressureFactor
        public StylusPoint(double x, double y, float pressureFactor) 
            : this(x, y, pressureFactor, null, null, false, true) 
        {
        } 


        /// 
        /// StylusPoint 
        /// 
        /// x 
        /// y 
        /// pressureFactor
        /// stylusPointDescription 
        /// additionalValues
        public StylusPoint(double x, double y, float pressureFactor, StylusPointDescription stylusPointDescription, int[] additionalValues)
            : this(x, y, pressureFactor, stylusPointDescription, additionalValues, true, true)
        { 
        }
 
        ///  
        /// internal ctor
        ///  
        internal StylusPoint(
            double x,
            double y,
            float pressureFactor, 
            StylusPointDescription stylusPointDescription,
            int[] additionalValues, 
            bool validateAdditionalData, 
            bool validatePressureFactor)
        { 
            if (Double.IsNaN(x))
            {
                throw new ArgumentOutOfRangeException("x", SR.Get(SRID.InvalidStylusPointXYNaN));
            } 
            if (Double.IsNaN(y))
            { 
                throw new ArgumentOutOfRangeException("y", SR.Get(SRID.InvalidStylusPointXYNaN)); 
            }
 

            //we don't validate pressure when called by StylusPointDescription.Reformat
            if (validatePressureFactor &&
                (pressureFactor == Single.NaN || pressureFactor < 0.0f || pressureFactor > 1.0f)) 
            {
                throw new ArgumentOutOfRangeException("pressureFactor", SR.Get(SRID.InvalidPressureValue)); 
            } 
            //
            // only accept values between MaxXY and MinXY 
            // we don't throw when passed a value outside of that range, we just silently trunctate
            //
            _x = GetClampedXYValue(x);
            _y = GetClampedXYValue(y); 
            _stylusPointDescription = stylusPointDescription;
            _additionalValues = additionalValues; 
            _pressureFactor = pressureFactor; 

            if (validateAdditionalData) 
            {

                //
                // called from the public verbose ctor 
                //
                if (null == stylusPointDescription) 
                { 
                    throw new ArgumentNullException("stylusPointDescription");
                } 

                //
                // additionalValues can be null if PropertyCount == 3 (X, Y, P)
                // 
                if (stylusPointDescription.PropertyCount > StylusPointDescription.RequiredCountOfProperties &&
                    null == additionalValues) 
                { 
                    throw new ArgumentNullException("additionalValues");
                } 


                if (additionalValues != null)
                { 
                    ReadOnlyCollection properties
                        = stylusPointDescription.GetStylusPointProperties(); 
 
                    int expectedAdditionalValues = properties.Count - StylusPointDescription.RequiredCountOfProperties; //for x, y, pressure
                    if (additionalValues.Length != expectedAdditionalValues) 
                    {
                        throw new ArgumentException(SR.Get(SRID.InvalidAdditionalDataForStylusPoint), "additionalValues");
                    }
 
                    //
                    // any buttons passed in must each be in their own int.  We need to 
                    // pack them all into one int here 
                    //
                    int[] newAdditionalValues = 
                        new int[stylusPointDescription.GetExpectedAdditionalDataCount()];

                    _additionalValues = newAdditionalValues;
                    for (int i = StylusPointDescription.RequiredCountOfProperties, j = 0; i < properties.Count; i++, j++) 
                    {
                        // 
                        // use SetPropertyValue, it validates buttons, but does not copy the 
                        // int[] on writes (since we pass the bool flag)
                        // 
                        SetPropertyValue(properties[i], additionalValues[j], false/*copy on write*/);
                    }
                }
            } 
        }
 
 

        #endregion Constructors 

        /// 
        /// The Maximum X or Y value supported for backwards compatibility with previous inking platforms
        ///  
        public static readonly double MaxXY = 81164736.28346430d;
 
        ///  
        /// The Minimum X or Y value supported for backwards compatibility with previous inking platforms
        ///  
        public static readonly double MinXY = -81164736.32125960d;

        /// 
        /// X 
        /// 
        public double X 
        { 
            get { return _x; }
            set 
            {
                if (Double.IsNaN(value))
                {
                    throw new ArgumentOutOfRangeException("X", SR.Get(SRID.InvalidStylusPointXYNaN)); 
                }
                // 
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _x = GetClampedXYValue(value);
            }
        }
 
        /// 
        /// Y 
        ///  
        public double Y
        { 
            get { return _y; }
            set
            {
                if (Double.IsNaN(value)) 
                {
                    throw new ArgumentOutOfRangeException("Y", SR.Get(SRID.InvalidStylusPointXYNaN)); 
                } 
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                //
                _y = GetClampedXYValue(value);
            } 
        }
 
        ///  
        /// PressureFactor.  A value between 0.0 (no pressure) and 1.0 (max pressure)
        ///  
        public float PressureFactor
        {
            get
            { 
                //
                // note that pressure can be stored a > 1 or < 0. 
                // we need to clamp if this is the case 
                //
                if (_pressureFactor > 1.0f) 
                {
                    return 1.0f;
                }
                if (_pressureFactor < 0.0f) 
                {
                    return 0.0f; 
                } 
                return _pressureFactor;
            } 
            set
            {
                if (value < 0.0f || value > 1.0f)
                { 
                    throw new ArgumentOutOfRangeException("PressureFactor", SR.Get(SRID.InvalidPressureValue));
                } 
                _pressureFactor = value; 
            }
        } 

        /// 
        /// Describes the properties this StylusPoint contains
        ///  
        public StylusPointDescription Description
        { 
            get 
            {
                if (null == _stylusPointDescription) 
                {
                    // this can happen when you call new StylusPoint()
                    // a few of the ctor's lazy init this as well
                    _stylusPointDescription = new StylusPointDescription(); 
                }
                return _stylusPointDescription; 
            } 
            internal set
            { 
                //
                // called by StylusPointCollection.Add / Set
                // to replace the StylusPoint.Description with the collections.
                // 
                Debug.Assert(value != null &&
                    StylusPointDescription.AreCompatible(value, this.Description)); 
 
                _stylusPointDescription = value;
            } 
        }

        /// 
        /// Returns true if this StylusPoint supports the specified property 
        /// 
        /// The StylusPointProperty to see if this StylusPoint supports 
        public bool HasProperty(StylusPointProperty stylusPointProperty) 
        {
            return this.Description.HasProperty(stylusPointProperty); 
        }

        /// 
        /// Provides read access to all stylus properties 
        /// 
        /// The StylusPointPropertyIds of the property to retrieve 
        public int GetPropertyValue(StylusPointProperty stylusPointProperty) 
        {
            if (null == stylusPointProperty) 
            {
                throw new ArgumentNullException("stylusPointProperty");
            }
            if (stylusPointProperty.Id == StylusPointPropertyIds.X) 
            {
                return (int)_x; 
            } 
            else if (stylusPointProperty.Id == StylusPointPropertyIds.Y)
            { 
                return (int)_y;
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.NormalPressure)
            { 
                StylusPointPropertyInfo info =
                    this.Description.GetPropertyInfo(StylusPointProperties.NormalPressure); 
 
                int max = info.Maximum;
                return (int)(_pressureFactor * (float)max); 
            }
            else
            {
                int propertyIndex = this.Description.GetPropertyIndex(stylusPointProperty.Id); 
                if (-1 == propertyIndex)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidStylusPointProperty), "stylusPointProperty"); 
                }
                if (stylusPointProperty.IsButton) 
                {
                    //
                    // we get button data from a single int in the array
                    // 
                    int buttonData = _additionalValues[_additionalValues.Length - 1];
                    int buttonBitPosition = this.Description.GetButtonBitPosition(stylusPointProperty); 
                    int bit = 1 << buttonBitPosition; 
                    if ((buttonData & bit) != 0)
                    { 
                        return 1;
                    }
                    else
                    { 
                        return 0;
                    } 
                } 
                else
                { 
                    return _additionalValues[propertyIndex - 3];
                }
            }
        } 

        ///  
        /// Allows supported properties to be set 
        /// 
        /// The property to set, it must exist on this StylusPoint 
        /// value
        public void SetPropertyValue(StylusPointProperty stylusPointProperty, int value)
        {
            SetPropertyValue(stylusPointProperty, value, true); 
        }
        ///  
        /// Optimization that lets the ctor call setvalue repeatly without causing a copy of the int[] 
        /// 
        /// stylusPointProperty 
        /// value
        /// 
        internal void SetPropertyValue(StylusPointProperty stylusPointProperty, int value, bool copyBeforeWrite)
        { 
            if (null == stylusPointProperty)
            { 
                throw new ArgumentNullException("stylusPointProperty"); 
            }
            if (stylusPointProperty.Id == StylusPointPropertyIds.X) 
            {
                double dVal = (double)value;
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _x = GetClampedXYValue(dVal); 
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.Y) 
            {
                double dVal = (double)value;
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _y = GetClampedXYValue(dVal); 
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.NormalPressure) 
            {
                StylusPointPropertyInfo info =
                    this.Description.GetPropertyInfo(StylusPointProperties.NormalPressure);
 
                int min = info.Minimum;
                int max = info.Maximum; 
                if (max == 0) 
                {
                    _pressureFactor = 0.0f; 
                }
                else
                {
                    _pressureFactor = (float)(Convert.ToSingle(min + value) / Convert.ToSingle(max)); 
                }
            } 
            else 
            {
                int propertyIndex = this.Description.GetPropertyIndex(stylusPointProperty.Id); 
                if (-1 == propertyIndex)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidStylusPointProperty), "propertyId");
                } 
                if (stylusPointProperty.IsButton)
                { 
                    if (value < 0 || value > 1) 
                    {
                        throw new ArgumentOutOfRangeException(SR.Get(SRID.InvalidMinMaxForButton), "value"); 
                    }

                    if (copyBeforeWrite)
                    { 
                        CopyAdditionalData();
                    } 
 
                    //
                    // we get button data from a single int in the array 
                    //
                    int buttonData = _additionalValues[_additionalValues.Length - 1];
                    int buttonBitPosition = this.Description.GetButtonBitPosition(stylusPointProperty);
                    int bit = 1 << buttonBitPosition; 
                    if (value == 0)
                    { 
                        //turn the bit off 
                        buttonData &= ~bit;
                    } 
                    else
                    {
                        //turn the bit on
                        buttonData |= bit; 
                    }
                    _additionalValues[_additionalValues.Length - 1] = buttonData; 
                } 
                else
                { 
                    if (copyBeforeWrite)
                    {
                        CopyAdditionalData();
                    } 
                    _additionalValues[propertyIndex - 3] = value;
                } 
            } 
        }
 
        /// 
        /// Explicit cast converter between StylusPoint and Point
        /// 
        /// stylusPoint 
        public static explicit operator Point(StylusPoint stylusPoint)
        { 
            return new Point(stylusPoint.X, stylusPoint.Y); 
        }
 
        /// 
        /// Allows languages that don't support operator overloading
        /// to convert to a point
        ///  
        public Point ToPoint()
        { 
            return new Point(this.X, this.Y); 
        }
 

        /// 
        /// Compares two StylusPoint instances for exact equality.
        /// Note that double values can acquire error when operated upon, such that 
        /// an exact comparison between two values which are logically equal may fail.
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself. 
        /// Descriptions must match for equality to succeed and additional values must match 
        /// 
        ///  
        /// bool - true if the two Stylus instances are exactly equal, false otherwise
        /// 
        /// The first StylusPoint to compare
        /// The second StylusPoint to compare 
        public static bool operator ==(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        { 
            return StylusPoint.Equals(stylusPoint1, stylusPoint2); 
        }
 
        /// 
        /// Compares two StylusPoint instances for exact inequality.
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail. 
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        ///  
        ///  
        /// bool - true if the two Stylus instances are exactly inequal, false otherwise
        ///  
        /// The first StylusPoint to compare
        /// The second StylusPoint to compare
        public static bool operator !=(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        { 
            return !StylusPoint.Equals(stylusPoint1, stylusPoint2);
        } 
 
        /// 
        /// Compares two StylusPoint instances for exact equality. 
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail.
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        /// Descriptions must match for equality to succeed and additional values must match 
        /// 
        ///  
        /// bool - true if the two Stylus instances are exactly equal, false otherwise 
        /// 
        /// The first StylusPoint to compare 
        /// The second StylusPoint to compare
        public static bool Equals(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        {
            // 
            // do the cheap comparison first
            // 
            bool membersEqual = 
                stylusPoint1._x == stylusPoint2._x &&
                stylusPoint1._y == stylusPoint2._y && 
                stylusPoint1._pressureFactor == stylusPoint2._pressureFactor;

            if (!membersEqual)
            { 
                return false;
            } 
 
            //
            // before we go checking the descriptions... check to see if both additionalData's are null 
            // we can infer that the SPD's are just X,Y,P and that they are compatible.
            //
            if (stylusPoint1._additionalValues == null &&
                stylusPoint2._additionalValues == null) 
            {
                Debug.Assert(StylusPointDescription.AreCompatible(stylusPoint1.Description, stylusPoint2.Description)); 
                return true; 
            }
 
            //
            // ok, the members are equal.  compare the description and then additional data
            //
            if (object.ReferenceEquals(stylusPoint1.Description, stylusPoint2.Description) || 
                StylusPointDescription.AreCompatible(stylusPoint1.Description, stylusPoint2.Description))
            { 
                // 
                // descriptions match and there are equal numbers of additional values
                // let's check the values 
                //
                for (int x = 0; x < stylusPoint1._additionalValues.Length; x++)
                {
                    if (stylusPoint1._additionalValues[x] != stylusPoint2._additionalValues[x]) 
                    {
                        return false; 
                    } 
                }
 
                //
                // Ok, ok already, we're equal
                //
                return true; 
            }
 
            return false; 
        }
 
        /// 
        /// Compares two StylusPoint instances for exact equality.
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail. 
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        /// Descriptions must match for equality to succeed and additional values must match 
        ///  
        /// 
        /// bool - true if the object is an instance of StylusPoint and if it's equal to "this". 
        /// 
        /// The object to compare to "this"
        public override bool Equals(object o)
        { 
            if ((null == o) || !(o is StylusPoint))
            { 
                return false; 
            }
 
            StylusPoint value = (StylusPoint)o;
            return StylusPoint.Equals(this, value);
        }
 
        /// 
        /// Equals - compares this StylusPoint with the passed in object.  In this equality 
        /// Double.NaN is equal to itself, unlike in numeric equality. 
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which 
        /// are logically equal may fail.
        /// 
        /// 
        /// bool - true if "value" is equal to "this". 
        /// 
        /// The StylusPoint to compare to "this" 
        public bool Equals(StylusPoint value) 
        {
            return StylusPoint.Equals(this, value); 
        }
        /// 
        /// Returns the HashCode for this StylusPoint
        ///  
        /// 
        /// int - the HashCode for this StylusPoint 
        ///  
        public override int GetHashCode()
        { 
            int hash =
                _x.GetHashCode() ^
                _y.GetHashCode() ^
                _pressureFactor.GetHashCode(); 

            if (_stylusPointDescription != null) 
            { 
                hash ^= _stylusPointDescription.GetHashCode();
            } 

            if (_additionalValues != null)
            {
                for (int x = 0; x < _additionalValues.Length; x++) 
                {
                    hash ^= _additionalValues[x]; //don't call GetHashCode on integers, it just returns the int 
                } 
            }
 
            return hash;
        }

        ///  
        /// Used by the StylusPointCollection.ToHimetricArray method
        ///  
        ///  
        internal int[] GetAdditionalData()
        { 
            //return a direct ref
            return _additionalValues;
        }
 
        /// 
        /// Internal helper used by SPC.Reformat to preserve the pressureFactor 
        ///  
        internal float GetUntruncatedPressureFactor()
        { 
            return _pressureFactor;
        }

        ///  
        /// GetPacketData - returns avalon space packet data with true pressure if it exists
        ///  
        internal int[] GetPacketData() 
        {
            int count = 2; //x, y 
            if (_additionalValues != null)
            {
                count += _additionalValues.Length;
            } 
            if (this.Description.ContainsTruePressure)
            { 
                count++; 
            }
            int[] data = new int[count]; 
            data[0] = (int)_x;
            data[1] = (int)_y;
            int startIndex = 2;
            if (this.Description.ContainsTruePressure) 
            {
                startIndex = 3; 
                data[2] = GetPropertyValue(StylusPointProperties.NormalPressure); 
            }
            if (_additionalValues != null) 
            {
                for (int x = 0; x < _additionalValues.Length; x++)
                {
                    data[x + startIndex] = _additionalValues[x]; 
                }
            } 
            return data; 
        }
 
        /// 
        /// Internal helper to determine if a stroke has default pressure
        /// This is used by ISF serialization to not serialize pressure
        ///  
        internal bool HasDefaultPressure
        { 
            get 
            {
                return (_pressureFactor == DefaultPressure); 
            }
        }

        ///  
        /// Used by the SetPropertyData to make a copy of the data
        /// before modifying it.  This is required so that we don't 
        /// have two StylusPoint's sharing the same int[] 
        /// which can happen when you call: StylusPoint p = otherStylusPoint
        /// because the CLR just does a memberwise copy 
        /// 
        /// 
        private void CopyAdditionalData()
        { 
            if (null != _additionalValues)
            { 
                int[] newData = new int[_additionalValues.Length]; 
                for (int x = 0; x < _additionalValues.Length; x++)
                { 
                    newData[x] = _additionalValues[x];
                }

                _additionalValues = newData; 
            }
        } 
 
        /// 
        /// Private helper that returns a double clamped to MaxXY or MinXY 
        /// We only accept values in this range to support ISF serialization
        /// 
        private static double GetClampedXYValue(double xyValue)
        { 
            if (xyValue > MaxXY)
            { 
                return MaxXY; 
            }
            if (xyValue < MinXY) 
            {
                return MinXY;
            }
 
            return xyValue;
        } 
    } 
}

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

using System; 
using System.Windows; 
using System.Diagnostics;
using System.Windows.Input; 
using System.Windows.Media;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using MS.Utility; 
using MS.Internal;
using SR = MS.Internal.PresentationCore.SR; 
using SRID = MS.Internal.PresentationCore.SRID; 

namespace System.Windows.Input 
{
    /// 
    /// Represents a single sampling point from a stylus input device
    ///  
    public struct StylusPoint : IEquatable
    { 
        internal static readonly float DefaultPressure = 0.5f; 

 
        private double _x;
        private double _y;
        private float _pressureFactor;
        private int[] _additionalValues; 
        private StylusPointDescription _stylusPointDescription;
 
        #region Constructors 
        /// 
        /// StylusPoint 
        /// 
        /// x
        /// y
        public StylusPoint(double x, double y) 
            : this(x, y, DefaultPressure, null, null, false, false)
        { 
        } 

        ///  
        /// StylusPoint
        /// 
        /// x
        /// y 
        /// pressureFactor
        public StylusPoint(double x, double y, float pressureFactor) 
            : this(x, y, pressureFactor, null, null, false, true) 
        {
        } 


        /// 
        /// StylusPoint 
        /// 
        /// x 
        /// y 
        /// pressureFactor
        /// stylusPointDescription 
        /// additionalValues
        public StylusPoint(double x, double y, float pressureFactor, StylusPointDescription stylusPointDescription, int[] additionalValues)
            : this(x, y, pressureFactor, stylusPointDescription, additionalValues, true, true)
        { 
        }
 
        ///  
        /// internal ctor
        ///  
        internal StylusPoint(
            double x,
            double y,
            float pressureFactor, 
            StylusPointDescription stylusPointDescription,
            int[] additionalValues, 
            bool validateAdditionalData, 
            bool validatePressureFactor)
        { 
            if (Double.IsNaN(x))
            {
                throw new ArgumentOutOfRangeException("x", SR.Get(SRID.InvalidStylusPointXYNaN));
            } 
            if (Double.IsNaN(y))
            { 
                throw new ArgumentOutOfRangeException("y", SR.Get(SRID.InvalidStylusPointXYNaN)); 
            }
 

            //we don't validate pressure when called by StylusPointDescription.Reformat
            if (validatePressureFactor &&
                (pressureFactor == Single.NaN || pressureFactor < 0.0f || pressureFactor > 1.0f)) 
            {
                throw new ArgumentOutOfRangeException("pressureFactor", SR.Get(SRID.InvalidPressureValue)); 
            } 
            //
            // only accept values between MaxXY and MinXY 
            // we don't throw when passed a value outside of that range, we just silently trunctate
            //
            _x = GetClampedXYValue(x);
            _y = GetClampedXYValue(y); 
            _stylusPointDescription = stylusPointDescription;
            _additionalValues = additionalValues; 
            _pressureFactor = pressureFactor; 

            if (validateAdditionalData) 
            {

                //
                // called from the public verbose ctor 
                //
                if (null == stylusPointDescription) 
                { 
                    throw new ArgumentNullException("stylusPointDescription");
                } 

                //
                // additionalValues can be null if PropertyCount == 3 (X, Y, P)
                // 
                if (stylusPointDescription.PropertyCount > StylusPointDescription.RequiredCountOfProperties &&
                    null == additionalValues) 
                { 
                    throw new ArgumentNullException("additionalValues");
                } 


                if (additionalValues != null)
                { 
                    ReadOnlyCollection properties
                        = stylusPointDescription.GetStylusPointProperties(); 
 
                    int expectedAdditionalValues = properties.Count - StylusPointDescription.RequiredCountOfProperties; //for x, y, pressure
                    if (additionalValues.Length != expectedAdditionalValues) 
                    {
                        throw new ArgumentException(SR.Get(SRID.InvalidAdditionalDataForStylusPoint), "additionalValues");
                    }
 
                    //
                    // any buttons passed in must each be in their own int.  We need to 
                    // pack them all into one int here 
                    //
                    int[] newAdditionalValues = 
                        new int[stylusPointDescription.GetExpectedAdditionalDataCount()];

                    _additionalValues = newAdditionalValues;
                    for (int i = StylusPointDescription.RequiredCountOfProperties, j = 0; i < properties.Count; i++, j++) 
                    {
                        // 
                        // use SetPropertyValue, it validates buttons, but does not copy the 
                        // int[] on writes (since we pass the bool flag)
                        // 
                        SetPropertyValue(properties[i], additionalValues[j], false/*copy on write*/);
                    }
                }
            } 
        }
 
 

        #endregion Constructors 

        /// 
        /// The Maximum X or Y value supported for backwards compatibility with previous inking platforms
        ///  
        public static readonly double MaxXY = 81164736.28346430d;
 
        ///  
        /// The Minimum X or Y value supported for backwards compatibility with previous inking platforms
        ///  
        public static readonly double MinXY = -81164736.32125960d;

        /// 
        /// X 
        /// 
        public double X 
        { 
            get { return _x; }
            set 
            {
                if (Double.IsNaN(value))
                {
                    throw new ArgumentOutOfRangeException("X", SR.Get(SRID.InvalidStylusPointXYNaN)); 
                }
                // 
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _x = GetClampedXYValue(value);
            }
        }
 
        /// 
        /// Y 
        ///  
        public double Y
        { 
            get { return _y; }
            set
            {
                if (Double.IsNaN(value)) 
                {
                    throw new ArgumentOutOfRangeException("Y", SR.Get(SRID.InvalidStylusPointXYNaN)); 
                } 
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                //
                _y = GetClampedXYValue(value);
            } 
        }
 
        ///  
        /// PressureFactor.  A value between 0.0 (no pressure) and 1.0 (max pressure)
        ///  
        public float PressureFactor
        {
            get
            { 
                //
                // note that pressure can be stored a > 1 or < 0. 
                // we need to clamp if this is the case 
                //
                if (_pressureFactor > 1.0f) 
                {
                    return 1.0f;
                }
                if (_pressureFactor < 0.0f) 
                {
                    return 0.0f; 
                } 
                return _pressureFactor;
            } 
            set
            {
                if (value < 0.0f || value > 1.0f)
                { 
                    throw new ArgumentOutOfRangeException("PressureFactor", SR.Get(SRID.InvalidPressureValue));
                } 
                _pressureFactor = value; 
            }
        } 

        /// 
        /// Describes the properties this StylusPoint contains
        ///  
        public StylusPointDescription Description
        { 
            get 
            {
                if (null == _stylusPointDescription) 
                {
                    // this can happen when you call new StylusPoint()
                    // a few of the ctor's lazy init this as well
                    _stylusPointDescription = new StylusPointDescription(); 
                }
                return _stylusPointDescription; 
            } 
            internal set
            { 
                //
                // called by StylusPointCollection.Add / Set
                // to replace the StylusPoint.Description with the collections.
                // 
                Debug.Assert(value != null &&
                    StylusPointDescription.AreCompatible(value, this.Description)); 
 
                _stylusPointDescription = value;
            } 
        }

        /// 
        /// Returns true if this StylusPoint supports the specified property 
        /// 
        /// The StylusPointProperty to see if this StylusPoint supports 
        public bool HasProperty(StylusPointProperty stylusPointProperty) 
        {
            return this.Description.HasProperty(stylusPointProperty); 
        }

        /// 
        /// Provides read access to all stylus properties 
        /// 
        /// The StylusPointPropertyIds of the property to retrieve 
        public int GetPropertyValue(StylusPointProperty stylusPointProperty) 
        {
            if (null == stylusPointProperty) 
            {
                throw new ArgumentNullException("stylusPointProperty");
            }
            if (stylusPointProperty.Id == StylusPointPropertyIds.X) 
            {
                return (int)_x; 
            } 
            else if (stylusPointProperty.Id == StylusPointPropertyIds.Y)
            { 
                return (int)_y;
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.NormalPressure)
            { 
                StylusPointPropertyInfo info =
                    this.Description.GetPropertyInfo(StylusPointProperties.NormalPressure); 
 
                int max = info.Maximum;
                return (int)(_pressureFactor * (float)max); 
            }
            else
            {
                int propertyIndex = this.Description.GetPropertyIndex(stylusPointProperty.Id); 
                if (-1 == propertyIndex)
                { 
                    throw new ArgumentException(SR.Get(SRID.InvalidStylusPointProperty), "stylusPointProperty"); 
                }
                if (stylusPointProperty.IsButton) 
                {
                    //
                    // we get button data from a single int in the array
                    // 
                    int buttonData = _additionalValues[_additionalValues.Length - 1];
                    int buttonBitPosition = this.Description.GetButtonBitPosition(stylusPointProperty); 
                    int bit = 1 << buttonBitPosition; 
                    if ((buttonData & bit) != 0)
                    { 
                        return 1;
                    }
                    else
                    { 
                        return 0;
                    } 
                } 
                else
                { 
                    return _additionalValues[propertyIndex - 3];
                }
            }
        } 

        ///  
        /// Allows supported properties to be set 
        /// 
        /// The property to set, it must exist on this StylusPoint 
        /// value
        public void SetPropertyValue(StylusPointProperty stylusPointProperty, int value)
        {
            SetPropertyValue(stylusPointProperty, value, true); 
        }
        ///  
        /// Optimization that lets the ctor call setvalue repeatly without causing a copy of the int[] 
        /// 
        /// stylusPointProperty 
        /// value
        /// 
        internal void SetPropertyValue(StylusPointProperty stylusPointProperty, int value, bool copyBeforeWrite)
        { 
            if (null == stylusPointProperty)
            { 
                throw new ArgumentNullException("stylusPointProperty"); 
            }
            if (stylusPointProperty.Id == StylusPointPropertyIds.X) 
            {
                double dVal = (double)value;
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _x = GetClampedXYValue(dVal); 
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.Y) 
            {
                double dVal = (double)value;
                //
                // only accept values between MaxXY and MinXY 
                // we don't throw when passed a value outside of that range, we just silently trunctate
                // 
                _y = GetClampedXYValue(dVal); 
            }
            else if (stylusPointProperty.Id == StylusPointPropertyIds.NormalPressure) 
            {
                StylusPointPropertyInfo info =
                    this.Description.GetPropertyInfo(StylusPointProperties.NormalPressure);
 
                int min = info.Minimum;
                int max = info.Maximum; 
                if (max == 0) 
                {
                    _pressureFactor = 0.0f; 
                }
                else
                {
                    _pressureFactor = (float)(Convert.ToSingle(min + value) / Convert.ToSingle(max)); 
                }
            } 
            else 
            {
                int propertyIndex = this.Description.GetPropertyIndex(stylusPointProperty.Id); 
                if (-1 == propertyIndex)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidStylusPointProperty), "propertyId");
                } 
                if (stylusPointProperty.IsButton)
                { 
                    if (value < 0 || value > 1) 
                    {
                        throw new ArgumentOutOfRangeException(SR.Get(SRID.InvalidMinMaxForButton), "value"); 
                    }

                    if (copyBeforeWrite)
                    { 
                        CopyAdditionalData();
                    } 
 
                    //
                    // we get button data from a single int in the array 
                    //
                    int buttonData = _additionalValues[_additionalValues.Length - 1];
                    int buttonBitPosition = this.Description.GetButtonBitPosition(stylusPointProperty);
                    int bit = 1 << buttonBitPosition; 
                    if (value == 0)
                    { 
                        //turn the bit off 
                        buttonData &= ~bit;
                    } 
                    else
                    {
                        //turn the bit on
                        buttonData |= bit; 
                    }
                    _additionalValues[_additionalValues.Length - 1] = buttonData; 
                } 
                else
                { 
                    if (copyBeforeWrite)
                    {
                        CopyAdditionalData();
                    } 
                    _additionalValues[propertyIndex - 3] = value;
                } 
            } 
        }
 
        /// 
        /// Explicit cast converter between StylusPoint and Point
        /// 
        /// stylusPoint 
        public static explicit operator Point(StylusPoint stylusPoint)
        { 
            return new Point(stylusPoint.X, stylusPoint.Y); 
        }
 
        /// 
        /// Allows languages that don't support operator overloading
        /// to convert to a point
        ///  
        public Point ToPoint()
        { 
            return new Point(this.X, this.Y); 
        }
 

        /// 
        /// Compares two StylusPoint instances for exact equality.
        /// Note that double values can acquire error when operated upon, such that 
        /// an exact comparison between two values which are logically equal may fail.
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself. 
        /// Descriptions must match for equality to succeed and additional values must match 
        /// 
        ///  
        /// bool - true if the two Stylus instances are exactly equal, false otherwise
        /// 
        /// The first StylusPoint to compare
        /// The second StylusPoint to compare 
        public static bool operator ==(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        { 
            return StylusPoint.Equals(stylusPoint1, stylusPoint2); 
        }
 
        /// 
        /// Compares two StylusPoint instances for exact inequality.
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail. 
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        ///  
        ///  
        /// bool - true if the two Stylus instances are exactly inequal, false otherwise
        ///  
        /// The first StylusPoint to compare
        /// The second StylusPoint to compare
        public static bool operator !=(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        { 
            return !StylusPoint.Equals(stylusPoint1, stylusPoint2);
        } 
 
        /// 
        /// Compares two StylusPoint instances for exact equality. 
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail.
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        /// Descriptions must match for equality to succeed and additional values must match 
        /// 
        ///  
        /// bool - true if the two Stylus instances are exactly equal, false otherwise 
        /// 
        /// The first StylusPoint to compare 
        /// The second StylusPoint to compare
        public static bool Equals(StylusPoint stylusPoint1, StylusPoint stylusPoint2)
        {
            // 
            // do the cheap comparison first
            // 
            bool membersEqual = 
                stylusPoint1._x == stylusPoint2._x &&
                stylusPoint1._y == stylusPoint2._y && 
                stylusPoint1._pressureFactor == stylusPoint2._pressureFactor;

            if (!membersEqual)
            { 
                return false;
            } 
 
            //
            // before we go checking the descriptions... check to see if both additionalData's are null 
            // we can infer that the SPD's are just X,Y,P and that they are compatible.
            //
            if (stylusPoint1._additionalValues == null &&
                stylusPoint2._additionalValues == null) 
            {
                Debug.Assert(StylusPointDescription.AreCompatible(stylusPoint1.Description, stylusPoint2.Description)); 
                return true; 
            }
 
            //
            // ok, the members are equal.  compare the description and then additional data
            //
            if (object.ReferenceEquals(stylusPoint1.Description, stylusPoint2.Description) || 
                StylusPointDescription.AreCompatible(stylusPoint1.Description, stylusPoint2.Description))
            { 
                // 
                // descriptions match and there are equal numbers of additional values
                // let's check the values 
                //
                for (int x = 0; x < stylusPoint1._additionalValues.Length; x++)
                {
                    if (stylusPoint1._additionalValues[x] != stylusPoint2._additionalValues[x]) 
                    {
                        return false; 
                    } 
                }
 
                //
                // Ok, ok already, we're equal
                //
                return true; 
            }
 
            return false; 
        }
 
        /// 
        /// Compares two StylusPoint instances for exact equality.
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which are logically equal may fail. 
        /// Furthermore, using this equality operator, Double.NaN is not equal to itself.
        /// Descriptions must match for equality to succeed and additional values must match 
        ///  
        /// 
        /// bool - true if the object is an instance of StylusPoint and if it's equal to "this". 
        /// 
        /// The object to compare to "this"
        public override bool Equals(object o)
        { 
            if ((null == o) || !(o is StylusPoint))
            { 
                return false; 
            }
 
            StylusPoint value = (StylusPoint)o;
            return StylusPoint.Equals(this, value);
        }
 
        /// 
        /// Equals - compares this StylusPoint with the passed in object.  In this equality 
        /// Double.NaN is equal to itself, unlike in numeric equality. 
        /// Note that double values can acquire error when operated upon, such that
        /// an exact comparison between two values which 
        /// are logically equal may fail.
        /// 
        /// 
        /// bool - true if "value" is equal to "this". 
        /// 
        /// The StylusPoint to compare to "this" 
        public bool Equals(StylusPoint value) 
        {
            return StylusPoint.Equals(this, value); 
        }
        /// 
        /// Returns the HashCode for this StylusPoint
        ///  
        /// 
        /// int - the HashCode for this StylusPoint 
        ///  
        public override int GetHashCode()
        { 
            int hash =
                _x.GetHashCode() ^
                _y.GetHashCode() ^
                _pressureFactor.GetHashCode(); 

            if (_stylusPointDescription != null) 
            { 
                hash ^= _stylusPointDescription.GetHashCode();
            } 

            if (_additionalValues != null)
            {
                for (int x = 0; x < _additionalValues.Length; x++) 
                {
                    hash ^= _additionalValues[x]; //don't call GetHashCode on integers, it just returns the int 
                } 
            }
 
            return hash;
        }

        ///  
        /// Used by the StylusPointCollection.ToHimetricArray method
        ///  
        ///  
        internal int[] GetAdditionalData()
        { 
            //return a direct ref
            return _additionalValues;
        }
 
        /// 
        /// Internal helper used by SPC.Reformat to preserve the pressureFactor 
        ///  
        internal float GetUntruncatedPressureFactor()
        { 
            return _pressureFactor;
        }

        ///  
        /// GetPacketData - returns avalon space packet data with true pressure if it exists
        ///  
        internal int[] GetPacketData() 
        {
            int count = 2; //x, y 
            if (_additionalValues != null)
            {
                count += _additionalValues.Length;
            } 
            if (this.Description.ContainsTruePressure)
            { 
                count++; 
            }
            int[] data = new int[count]; 
            data[0] = (int)_x;
            data[1] = (int)_y;
            int startIndex = 2;
            if (this.Description.ContainsTruePressure) 
            {
                startIndex = 3; 
                data[2] = GetPropertyValue(StylusPointProperties.NormalPressure); 
            }
            if (_additionalValues != null) 
            {
                for (int x = 0; x < _additionalValues.Length; x++)
                {
                    data[x + startIndex] = _additionalValues[x]; 
                }
            } 
            return data; 
        }
 
        /// 
        /// Internal helper to determine if a stroke has default pressure
        /// This is used by ISF serialization to not serialize pressure
        ///  
        internal bool HasDefaultPressure
        { 
            get 
            {
                return (_pressureFactor == DefaultPressure); 
            }
        }

        ///  
        /// Used by the SetPropertyData to make a copy of the data
        /// before modifying it.  This is required so that we don't 
        /// have two StylusPoint's sharing the same int[] 
        /// which can happen when you call: StylusPoint p = otherStylusPoint
        /// because the CLR just does a memberwise copy 
        /// 
        /// 
        private void CopyAdditionalData()
        { 
            if (null != _additionalValues)
            { 
                int[] newData = new int[_additionalValues.Length]; 
                for (int x = 0; x < _additionalValues.Length; x++)
                { 
                    newData[x] = _additionalValues[x];
                }

                _additionalValues = newData; 
            }
        } 
 
        /// 
        /// Private helper that returns a double clamped to MaxXY or MinXY 
        /// We only accept values in this range to support ISF serialization
        /// 
        private static double GetClampedXYValue(double xyValue)
        { 
            if (xyValue > MaxXY)
            { 
                return MaxXY; 
            }
            if (xyValue < MinXY) 
            {
                return MinXY;
            }
 
            return xyValue;
        } 
    } 
}

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