Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Input / Stylus / StylusPoint.cs / 1305600 / 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("value", SR.Get(SRID.InvalidMinMaxForButton));
}
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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CopyAttributesAction.cs
- XmlParser.cs
- HijriCalendar.cs
- SrgsItemList.cs
- ClientSettings.cs
- DataGridViewComboBoxColumnDesigner.cs
- NavigationHelper.cs
- HttpCachePolicyElement.cs
- BinaryObjectReader.cs
- ResourceDefaultValueAttribute.cs
- MemberMaps.cs
- DesignerProperties.cs
- Stacktrace.cs
- AnnotationHighlightLayer.cs
- PenLineJoinValidation.cs
- QueryResults.cs
- SelfIssuedAuthAsymmetricKey.cs
- SchemaNames.cs
- XamlBuildTaskServices.cs
- CodeVariableDeclarationStatement.cs
- ThreadAttributes.cs
- CodeParameterDeclarationExpressionCollection.cs
- Control.cs
- Guid.cs
- NetStream.cs
- SizeAnimationClockResource.cs
- XmlSchemaSequence.cs
- LambdaCompiler.Address.cs
- TypeNameConverter.cs
- ExpressionContext.cs
- DesignerDataSchemaClass.cs
- SqlClientWrapperSmiStream.cs
- CommandBindingCollection.cs
- DocumentSchemaValidator.cs
- CommandDevice.cs
- EllipseGeometry.cs
- QilIterator.cs
- UInt32.cs
- Vector3DIndependentAnimationStorage.cs
- RowType.cs
- RepeaterDesigner.cs
- PriorityBinding.cs
- Attributes.cs
- contentDescriptor.cs
- SqlTriggerAttribute.cs
- ExcCanonicalXml.cs
- OSFeature.cs
- SHA384.cs
- TypeElement.cs
- EntityDataSourceDataSelectionPanel.cs
- XamlSerializer.cs
- Char.cs
- TextEffectCollection.cs
- RenderingEventArgs.cs
- FolderBrowserDialog.cs
- EncryptedType.cs
- Int64Storage.cs
- DeferrableContentConverter.cs
- MetadataSerializer.cs
- File.cs
- XmlTypeAttribute.cs
- FreezableCollection.cs
- MergablePropertyAttribute.cs
- SizeF.cs
- RunClient.cs
- IdentityValidationException.cs
- ChainOfResponsibility.cs
- UrlAuthorizationModule.cs
- BrowserCapabilitiesFactory.cs
- CatalogPartCollection.cs
- DynamicRendererThreadManager.cs
- VScrollBar.cs
- EventLogPermissionEntry.cs
- SynchronizedDispatch.cs
- ZipPackagePart.cs
- JumpTask.cs
- QueryCacheKey.cs
- DocumentViewerBase.cs
- PingOptions.cs
- EmptyEnumerable.cs
- PasswordTextContainer.cs
- SerializerProvider.cs
- CqlLexerHelpers.cs
- PartitionResolver.cs
- OdbcInfoMessageEvent.cs
- TextDpi.cs
- WebExceptionStatus.cs
- AttributeCollection.cs
- SmtpMail.cs
- DBAsyncResult.cs
- TraceSwitch.cs
- CharEnumerator.cs
- SingleTagSectionHandler.cs
- AlternateViewCollection.cs
- AccessControlEntry.cs
- XmlNamedNodeMap.cs
- ServiceDescriptions.cs
- CopyOnWriteList.cs
- EntityDataSourceView.cs
- QuerySettings.cs