/// <summary> /// StylusPointCollection /// </summary> /// <param name="stylusPoints">stylusPoints</param> public StylusPointCollection(IEnumerable <StylusPoint> stylusPoints) //: this() //don't call the base ctor, we want to use the first sp { if (stylusPoints == null) { throw new ArgumentNullException("stylusPoints"); } List <StylusPoint> points = new List <StylusPoint>(stylusPoints); if (points.Count == 0) { throw new ArgumentException(SR.Get(SRID.InvalidStylusPointConstructionZeroLengthCollection), "stylusPoints"); } // // set our packet description to the first in the array // _stylusPointDescription = points[0].Description; ((List <StylusPoint>) this.Items).Capacity = points.Count; for (int x = 0; x < points.Count; x++) { this.Add(points[x]); } }
/// <summary> /// Adds the StylusPoints in the StylusPointCollection to this StylusPointCollection /// </summary> /// <param name="stylusPoints">stylusPoints</param> public void Add(StylusPointCollection stylusPoints) { //note that we don't raise an exception if stylusPoints.Count == 0 if (null == stylusPoints) { throw new ArgumentNullException("stylusPoints"); } if (!StylusPointDescription.AreCompatible(stylusPoints.Description, _stylusPointDescription)) { throw new ArgumentException(SR.Get(SRID.IncompatibleStylusPointDescriptions), "stylusPoints"); } // cache count outside of the loop, so if this SPC is ever passed // we don't loop forever int count = stylusPoints.Count; for (int x = 0; x < count; x++) { StylusPoint stylusPoint = stylusPoints[x]; stylusPoint.Description = _stylusPointDescription; //this does not go through our protected virtuals ((List <StylusPoint>) this.Items).Add(stylusPoint); } if (stylusPoints.Count > 0) { OnChanged(EventArgs.Empty); } }
internal Point GetLastTabletPoint() { int packetLength = StylusPointDescription.GetInputArrayLengthPerPoint(); int lastXIndex = _data.Length - packetLength; return(new Point(_data[lastXIndex], _data[lastXIndex + 1])); }
/// <summary> /// Private clone implementation /// </summary> private StylusPointCollection Clone(GeneralTransform transform, StylusPointDescription descriptionToUse, int count) { Debug.Assert(count <= this.Count); // // We don't need to copy our _stylusPointDescription because it is immutable // and we don't need to copy our StylusPoints, because they are structs. // StylusPointCollection newCollection = new StylusPointCollection(descriptionToUse, count); bool isIdentity = (transform is Transform) ? ((Transform)transform).IsIdentity : false; for (int x = 0; x < count; x++) { if (isIdentity) { ((List <StylusPoint>)newCollection.Items).Add(this[x]); } else { Point point = new Point(); StylusPoint stylusPoint = this[x]; point.X = stylusPoint.X; point.Y = stylusPoint.Y; transform.TryTransform(point, out point); stylusPoint.X = point.X; stylusPoint.Y = point.Y; ((List <StylusPoint>)newCollection.Items).Add(stylusPoint); } } return(newCollection); }
internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawStylusActions actions, StylusPointDescription mousePointDescription, int[] mouseData) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (mouseData == null) { throw new ArgumentNullException("mouseData"); } _penContext = new SecurityCriticalDataClass <PenContext>(null); _actions = actions; _tabletDeviceId = 0; _stylusDeviceId = 0; _data = mouseData; _isSynchronize = false; _mousePointDescription = mousePointDescription; _isMouseInput = true; }
/// <summary> /// Internal ctor called by input with a raw int[] /// </summary> /// <param name="stylusPointDescription">stylusPointDescription</param> /// <param name="rawPacketData">rawPacketData</param> /// <param name="tabletToView">tabletToView</param> /// <param name="tabletToViewMatrix">tabletToView</param> internal StylusPointCollection(StylusPointDescription stylusPointDescription, int[] rawPacketData, GeneralTransform tabletToView, Matrix tabletToViewMatrix) { if (null == stylusPointDescription) { throw new ArgumentNullException("stylusPointDescription"); } _stylusPointDescription = stylusPointDescription; int lengthPerPoint = stylusPointDescription.GetInputArrayLengthPerPoint(); int logicalPointCount = rawPacketData.Length / lengthPerPoint; Debug.Assert(0 == rawPacketData.Length % lengthPerPoint, "Invalid assumption about packet length, there shouldn't be any remainder"); // // set our capacity and validate // ((List <StylusPoint>) this.Items).Capacity = logicalPointCount; for (int count = 0, i = 0; count < logicalPointCount; count++, i += lengthPerPoint) { //first, determine the x, y values by xf-ing them Point p = new Point(rawPacketData[i], rawPacketData[i + 1]); if (tabletToView != null) { tabletToView.TryTransform(p, out p); } else { p = tabletToViewMatrix.Transform(p); } int startIndex = 2; bool containsTruePressure = stylusPointDescription.ContainsTruePressure; if (containsTruePressure) { //don't copy pressure in the int[] for extra data startIndex++; } int[] data = null; int dataLength = lengthPerPoint - startIndex; if (dataLength > 0) { //copy the rest of the data var rawArrayStartIndex = i + startIndex; data = rawPacketData.AsSpan(rawArrayStartIndex, dataLength).ToArray(); } StylusPoint newPoint = new StylusPoint(p.X, p.Y, StylusPoint.DefaultPressure, _stylusPointDescription, data, false, false); if (containsTruePressure) { //use the algorithm to set pressure in StylusPoint int pressure = rawPacketData[i + 2]; newPoint.SetPropertyValue(StylusPointProperties.NormalPressure, pressure); } //this does not go through our protected virtuals ((List <StylusPoint>) this.Items).Add(newPoint); } }
/// <summary> /// StylusPointCollection /// </summary> /// <param name="stylusPointDescription">stylusPointDescription</param> public StylusPointCollection(StylusPointDescription stylusPointDescription) { if (null == stylusPointDescription) { throw new ArgumentNullException(); } _stylusPointDescription = stylusPointDescription; }
/// <summary> /// StylusPointCollection /// </summary> /// <param name="stylusPointDescription">stylusPointDescription</param> /// <param name="initialCapacity">initialCapacity</param> public StylusPointCollection(StylusPointDescription stylusPointDescription, int initialCapacity) : this(stylusPointDescription) { if (initialCapacity < 0) { throw new ArgumentException(SR.Get(SRID.InvalidStylusPointConstructionZeroLengthCollection), "initialCapacity"); } ((List <StylusPoint>) this.Items).Capacity = initialCapacity; }
/// <summary> /// 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 /// </summary> /// <returns> /// bool - true if the two Stylus instances are exactly equal, false otherwise /// </returns> /// <param name='stylusPoint1'>The first StylusPoint to compare</param> /// <param name='stylusPoint2'>The second StylusPoint to compare</param> 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); }
/// <summary> /// called by base class Collection<T> when an item is set in list; /// raises a CollectionChanged event to any listeners /// </summary> protected override sealed void SetItem(int index, StylusPoint stylusPoint) { if (!StylusPointDescription.AreCompatible(stylusPoint.Description, _stylusPointDescription)) { throw new ArgumentException(SR.Get(SRID.IncompatibleStylusPointDescriptions), "stylusPoint"); } stylusPoint.Description = _stylusPointDescription; base.SetItem(index, stylusPoint); OnChanged(EventArgs.Empty); }
/// <summary> /// Returns a new StylusPointDescription with the common StylusPointProperties from both /// </summary> /// <param name="stylusPointDescription">stylusPointDescription</param> /// <param name="stylusPointDescriptionPreserveInfo">stylusPointDescriptionPreserveInfo</param> /// <remarks>The StylusPointProperties from stylusPointDescriptionPreserveInfo will be returned in the new StylusPointDescription</remarks> public static StylusPointDescription GetCommonDescription(StylusPointDescription stylusPointDescription, StylusPointDescription stylusPointDescriptionPreserveInfo) { if (stylusPointDescription == null) { throw new ArgumentNullException("stylusPointDescription"); } if (stylusPointDescriptionPreserveInfo == null) { throw new ArgumentNullException("stylusPointDescriptionPreserveInfo"); } #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null. // // ignore X, Y, Pressure - they are guaranteed to be the first3 members // Debug.Assert(stylusPointDescription._stylusPointPropertyInfos.Length >= 3 && stylusPointDescription._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); Debug.Assert(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length >= 3 && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); //add x, y, p List <StylusPointPropertyInfo> commonProperties = new List <StylusPointPropertyInfo>(); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0]); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1]); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2]); //add common properties for (int x = RequiredCountOfProperties; x < stylusPointDescription._stylusPointPropertyInfos.Length; x++) { for (int y = RequiredCountOfProperties; y < stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length; y++) { if (StylusPointPropertyInfo.AreCompatible(stylusPointDescription._stylusPointPropertyInfos[x], stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y])) { commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y]); } } } #pragma warning restore 6506 return(new StylusPointDescription(commonProperties)); }
internal void UpdateSizeDeltas(StylusPointDescription description, StylusLogic stylusLogic) { if (_doubleTapSize.IsEmpty || _cancelSize.IsEmpty || _forceUpdateSizeDeltas) { // Query default settings for mouse drag and double tap (with minimum of 1x1 size). Size mouseDragDefault = new Size(Math.Max(1, SafeSystemMetrics.DragDeltaX / 2), Math.Max(1, SafeSystemMetrics.DragDeltaY / 2)); Size mouseDoubleTapDefault = new Size(Math.Max(1, SafeSystemMetrics.DoubleClickDeltaX / 2), Math.Max(1, SafeSystemMetrics.DoubleClickDeltaY / 2)); StylusPointPropertyInfo xProperty = description.GetPropertyInfo(StylusPointProperties.X); StylusPointPropertyInfo yProperty = description.GetPropertyInfo(StylusPointProperties.Y); uint dwXValue = GetPropertyValue(xProperty); uint dwYValue = GetPropertyValue(yProperty); if (dwXValue != 0 && dwYValue != 0) { _cancelSize = new Size((int)Math.Round((ScreenSize.Width * stylusLogic.CancelDelta) / dwXValue), (int)Math.Round((ScreenSize.Height * stylusLogic.CancelDelta) / dwYValue)); // Make sure we return whole numbers (pixels are whole numbers) and take the maximum // value between mouse and stylus settings to be safe. _cancelSize.Width = Math.Max(mouseDragDefault.Width, _cancelSize.Width); _cancelSize.Height = Math.Max(mouseDragDefault.Height, _cancelSize.Height); _doubleTapSize = new Size((int)Math.Round((ScreenSize.Width * stylusLogic.DoubleTapDelta) / dwXValue), (int)Math.Round((ScreenSize.Height * stylusLogic.DoubleTapDelta) / dwYValue)); // Make sure we return whole numbers (pixels are whole numbers) and take the maximum // value between mouse and stylus settings to be safe. _doubleTapSize.Width = Math.Max(mouseDoubleTapDefault.Width, _doubleTapSize.Width); _doubleTapSize.Height = Math.Max(mouseDoubleTapDefault.Height, _doubleTapSize.Height); } else { // If no info to do the calculation then use the mouse settings for the default. _doubleTapSize = mouseDoubleTapDefault; _cancelSize = mouseDragDefault; } _forceUpdateSizeDeltas = false; } }
/// <summary> /// Loads a stroke from the stream based on Stroke Descriptor, StylusPointDescription, Drawing Attributes, Stroke IDs, transform and GuidList /// </summary> /// <param name="stream"></param> /// <param name="size"></param> /// <param name="guidList"></param> /// <param name="strokeDescriptor"></param> /// <param name="stylusPointDescription"></param> /// <param name="drawingAttributes"></param> /// <param name="transform"></param> /// <param name="stroke">Newly decoded stroke</param> #endif internal static uint DecodeStroke(Stream stream, uint size, GuidList guidList, StrokeDescriptor strokeDescriptor, StylusPointDescription stylusPointDescription, DrawingAttributes drawingAttributes, Matrix transform, #if OLD_ISF Compressor compressor, #endif out Stroke stroke) { ExtendedPropertyCollection extendedProperties; StylusPointCollection stylusPoints; uint cb = DecodeISFIntoStroke( #if OLD_ISF compressor, #endif stream, size, guidList, strokeDescriptor, stylusPointDescription, transform, out stylusPoints, out extendedProperties); if (cb != size) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Stroke size (" + cb.ToString(System.Globalization.CultureInfo.InvariantCulture) + ") != expected (" + size.ToString(System.Globalization.CultureInfo.InvariantCulture) + ")")); } stroke = new Stroke(stylusPoints, drawingAttributes, extendedProperties); return cb; }
/// <summary> /// Returns true if this StylusPointDescription is a subset /// of the StylusPointDescription passed in /// </summary> /// <param name="stylusPointDescriptionSuperset">stylusPointDescriptionSuperset</param> /// <returns></returns> public bool IsSubsetOf(StylusPointDescription stylusPointDescriptionSuperset) { if (null == stylusPointDescriptionSuperset) { throw new ArgumentNullException("stylusPointDescriptionSuperset"); } if (stylusPointDescriptionSuperset._stylusPointPropertyInfos.Length < _stylusPointPropertyInfos.Length) { return(false); } // // iterate through our local properties and make sure that the // superset contains them // for (int x = 0; x < _stylusPointPropertyInfos.Length; x++) { Guid id = _stylusPointPropertyInfos[x].Id; if (-1 == stylusPointDescriptionSuperset.IndexOf(id)) { return(false); } } return(true); }
/// <summary> /// Returns true if the two StylusPointDescriptions have the same StylusPointProperties. Metrics are ignored. /// </summary> /// <param name="stylusPointDescription1">stylusPointDescription1</param> /// <param name="stylusPointDescription2">stylusPointDescription2</param> public static bool AreCompatible(StylusPointDescription stylusPointDescription1, StylusPointDescription stylusPointDescription2) { if (stylusPointDescription1 == null || stylusPointDescription2 == null) { throw new ArgumentNullException("stylusPointDescription"); } #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null. // // ignore X, Y, Pressure - they are guaranteed to be the first3 members // Debug.Assert(stylusPointDescription1._stylusPointPropertyInfos.Length >= RequiredCountOfProperties && stylusPointDescription1._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription1._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription1._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); Debug.Assert(stylusPointDescription2._stylusPointPropertyInfos.Length >= RequiredCountOfProperties && stylusPointDescription2._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription2._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription2._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); if (stylusPointDescription1._stylusPointPropertyInfos.Length != stylusPointDescription2._stylusPointPropertyInfos.Length) { return(false); } for (int x = RequiredCountOfProperties; x < stylusPointDescription1._stylusPointPropertyInfos.Length; x++) { if (!StylusPointPropertyInfo.AreCompatible(stylusPointDescription1._stylusPointPropertyInfos[x], stylusPointDescription2._stylusPointPropertyInfos[x])) { return(false); } } #pragma warning restore 6506 return(true); }
public StylusPoint(double x, double y, float pressureFactor, StylusPointDescription stylusPointDescription, int[] additionalValues) { }
internal RawStylusInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawStylusActions actions, StylusPointDescription mousePointDescription, int[] mouseData) : base(inputSource, InputType.Stylus, mode, timestamp) { // Validate parameters if (!RawStylusActionsHelper.IsValid(actions)) { throw new InvalidEnumArgumentException(SR.Get(SRID.Enum_Invalid, "actions")); } if (mouseData == null) { throw new ArgumentNullException("mouseData"); } _penContext = new SecurityCriticalDataClass<PenContext>(null); _actions = actions; _tabletDeviceId = 0; _stylusDeviceId = 0; _data = mouseData; _isSynchronize = false; _mousePointDescription = mousePointDescription; _isMouseInput = true; }
public StylusPointCollection GetStylusPoints(System.Windows.IInputElement relativeTo, StylusPointDescription subsetToReformatTo) { return default(StylusPointCollection); }
/// <summary> /// Returns true if this StylusPointDescription is a subset /// of the StylusPointDescription passed in /// </summary> /// <param name="stylusPointDescriptionSuperset">stylusPointDescriptionSuperset</param> /// <returns></returns> public bool IsSubsetOf(StylusPointDescription stylusPointDescriptionSuperset) { if (null == stylusPointDescriptionSuperset) { throw new ArgumentNullException("stylusPointDescriptionSuperset"); } if (stylusPointDescriptionSuperset._stylusPointPropertyInfos.Length < _stylusPointPropertyInfos.Length) { return false; } // // iterate through our local properties and make sure that the // superset contains them // for (int x = 0; x < _stylusPointPropertyInfos.Length; x++) { Guid id = _stylusPointPropertyInfos[x].Id; if (-1 == stylusPointDescriptionSuperset.IndexOf(id)) { return false; } } return true; }
/// <summary> /// Reformat /// </summary> /// <param name="subsetToReformatTo">subsetToReformatTo</param> public StylusPointCollection Reformat(StylusPointDescription subsetToReformatTo) { return(Reformat(subsetToReformatTo, System.Windows.Media.Transform.Identity)); }
/// <summary> /// This functions loads a stroke from a memory stream based on the descriptor and GuidList. It returns /// the no of bytes it has read from the stream to correctly load the stream, which should be same as /// the value of the size parameter. If they are unequal throws ArgumentException. Stroke descriptor is /// used to load the packetproperty as well as ExtendedPropertyCollection on this stroke. Compressor is used /// to decompress the data. /// </summary> /// <param name="stream"></param> /// <param name="totalBytesInStrokeBlockOfIsfStream"></param> /// <param name="guidList"></param> /// <param name="strokeDescriptor"></param> /// <param name="stylusPointDescription"></param> /// <param name="transform"></param> /// <param name="stylusPoints"></param> /// <param name="extendedProperties"></param> #endif static uint DecodeISFIntoStroke( #if OLD_ISF Compressor compressor, #endif Stream stream, uint totalBytesInStrokeBlockOfIsfStream, GuidList guidList, StrokeDescriptor strokeDescriptor, StylusPointDescription stylusPointDescription, Matrix transform, out StylusPointCollection stylusPoints, out ExtendedPropertyCollection extendedProperties) { stylusPoints = null; extendedProperties = null; // We do allow a stroke with no packet data if (0 == totalBytesInStrokeBlockOfIsfStream) { return 0; } uint locallyDecodedBytes; uint remainingBytesInStrokeBlock = totalBytesInStrokeBlockOfIsfStream; // First try to load any packet data locallyDecodedBytes = LoadPackets( stream, remainingBytesInStrokeBlock, #if OLD_ISF compressor, #endif stylusPointDescription, transform, out stylusPoints); if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Packet buffer overflowed the ISF stream")); remainingBytesInStrokeBlock -= locallyDecodedBytes; if (0 == remainingBytesInStrokeBlock) { return locallyDecodedBytes; } // Now read the extended propertes for (int iTag = 1; iTag < strokeDescriptor.Template.Count && remainingBytesInStrokeBlock > 0; iTag++) { KnownTagCache.KnownTagIndex tag = strokeDescriptor.Template[iTag - 1]; switch (tag) { case MS.Internal.Ink.InkSerializedFormat.KnownTagCache.KnownTagIndex.StrokePropertyList: { // we've found the stroke extended properties. Load them now. while (iTag < strokeDescriptor.Template.Count && remainingBytesInStrokeBlock > 0) { tag = strokeDescriptor.Template[iTag]; object data; Guid guid = guidList.FindGuid(tag); if (guid == Guid.Empty) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Stroke Custom Attribute tag embedded in ISF stream does not match guid table")); } // load the extended property data from the stream (and decode the type) locallyDecodedBytes = ExtendedPropertySerializer.DecodeAsISF(stream, remainingBytesInStrokeBlock, guidList, tag, ref guid, out data); // add the guid/data pair into the property collection (don't redecode the type) if (extendedProperties == null) { extendedProperties = new ExtendedPropertyCollection(); } extendedProperties[guid] = data; if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; iTag++; } } break; case MS.Internal.Ink.InkSerializedFormat.KnownTagCache.KnownTagIndex.Buttons: { // Next tag is count of buttons and the tags for the button guids iTag += (int)((uint)strokeDescriptor.Template[iTag]) + 1; } break; // ignore any tags embedded in the Stroke block that this // version of the ISF decoder doesn't understand default: { System.Diagnostics.Trace.WriteLine("Ignoring unhandled stroke tag in ISF stroke descriptor"); } break; } } // Now try to load any tagged property data or point property data while (remainingBytesInStrokeBlock > 0) { // Read the tag first KnownTagCache.KnownTagIndex tag; uint uiTag; locallyDecodedBytes = SerializationHelper.Decode(stream, out uiTag); tag = (KnownTagCache.KnownTagIndex)uiTag; if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; // if it is a point property block switch (tag) { case MS.Internal.Ink.InkSerializedFormat.KnownTagCache.KnownTagIndex.PointProperty: { // First load the totalBytesInStrokeBlockOfIsfStream of the point property block uint cbsize; locallyDecodedBytes = SerializationHelper.Decode(stream, out cbsize); if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; while (remainingBytesInStrokeBlock > 0) { // First read the tag corresponding to the property locallyDecodedBytes = SerializationHelper.Decode(stream, out uiTag); tag = (KnownTagCache.KnownTagIndex)uiTag; if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; // Now read the packet index for which the property will apply uint propindex; locallyDecodedBytes = SerializationHelper.Decode(stream, out propindex); if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; uint propsize; locallyDecodedBytes = SerializationHelper.Decode(stream, out propsize); if (locallyDecodedBytes > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); remainingBytesInStrokeBlock -= locallyDecodedBytes; // Compressed data totalBytesInStrokeBlockOfIsfStream propsize += 1; // Make sure we have enough data to read if (propsize > remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); byte[] in_buffer = new byte[propsize]; uint bytesRead = StrokeCollectionSerializer.ReliableRead(stream, in_buffer, propsize); if (propsize != bytesRead) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Read different size from stream then expected")); } byte[] out_buffer = Compressor.DecompressPropertyData(in_buffer); System.Diagnostics.Debug.Assert(false, "ExtendedProperties for points are not supported"); // skip the bytes in both success & failure cases // Note: Point ExtendedProperties are discarded remainingBytesInStrokeBlock -= propsize; } } break; default: { object data; Guid guid = guidList.FindGuid(tag); if (guid == Guid.Empty) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Stroke Custom Attribute tag embedded in ISF stream does not match guid table")); } // load the extended property data from the stream (and decode the type) locallyDecodedBytes = ExtendedPropertySerializer.DecodeAsISF(stream, remainingBytesInStrokeBlock, guidList, tag, ref guid, out data); // add the guid/data pair into the property collection (don't redecode the type) if (extendedProperties == null) { extendedProperties = new ExtendedPropertyCollection(); } extendedProperties[guid] = data; if (locallyDecodedBytes > remainingBytesInStrokeBlock) { throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage("ExtendedProperty decoded totalBytesInStrokeBlockOfIsfStream exceeded ISF stream totalBytesInStrokeBlockOfIsfStream")); } remainingBytesInStrokeBlock -= locallyDecodedBytes; } break; } } if (0 != remainingBytesInStrokeBlock) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); return totalBytesInStrokeBlockOfIsfStream; }
public StylusPointCollection(StylusPointDescription stylusPointDescription, int initialCapacity) { }
public StylusPointCollection(StylusPointDescription stylusPointDescription) { }
public System.Windows.Input.StylusPointCollection Reformat(StylusPointDescription subsetToReformatTo) { return(default(System.Windows.Input.StylusPointCollection)); }
private void InitStylusPointDescription() { int cProps; int cButtons; int pressureIndex = -1; // Make sure we are never called on the application thread when we need to talk // to penimc or else we can cause reentrancy! Debug.Assert(!_contexts._inputSource.Value.CheckAccess()); // We should always have a valid IPimcContext interface pointer. Debug.Assert(_pimcContext != null && _pimcContext.Value != null); _pimcContext.Value.GetPacketDescriptionInfo(out cProps, out cButtons); // Calls Unmanaged code - SecurityCritical with SUC. List<StylusPointPropertyInfo> propertyInfos = new List<StylusPointPropertyInfo>(cProps + cButtons + 3); for (int i = 0; i < cProps; i++) { Guid guid; int min, max; int units; float res; _pimcContext.Value.GetPacketPropertyInfo(i, out guid, out min, out max, out units, out res); // Calls Unmanaged code - SecurityCritical with SUC. if (pressureIndex == -1 && guid == StylusPointPropertyIds.NormalPressure) { pressureIndex = i; } if (_statusPropertyIndex == -1 && guid == StylusPointPropertyIds.PacketStatus) { _statusPropertyIndex = i; } StylusPointPropertyInfo propertyInfo = new StylusPointPropertyInfo(new StylusPointProperty(guid, false), min, max, (StylusPointPropertyUnit)units, res); propertyInfos.Add(propertyInfo); } Debug.Assert(_statusPropertyIndex != -1); // We should always see this. // Make sure we actually created propertyInfos OK if (propertyInfos != null) { for (int i = 0; i < cButtons; i++) { Guid buttonGuid; _pimcContext.Value.GetPacketButtonInfo(i, out buttonGuid); // Calls Unmanaged code - SecurityCritical with SUC. StylusPointProperty buttonProperty = new StylusPointProperty(buttonGuid, true); StylusPointPropertyInfo buttonInfo = new StylusPointPropertyInfo(buttonProperty); propertyInfos.Add(buttonInfo); } //validate we can never get X, Y at index != 0, 1 Debug.Assert(propertyInfos[StylusPointDescription.RequiredXIndex /*0*/].Id == StylusPointPropertyIds.X, "X isn't where we expect it! Fix PenImc to ask for X at index 0"); Debug.Assert(propertyInfos[StylusPointDescription.RequiredYIndex /*0*/].Id == StylusPointPropertyIds.Y, "Y isn't where we expect it! Fix PenImc to ask for Y at index 1"); Debug.Assert(pressureIndex == -1 || pressureIndex == StylusPointDescription.RequiredPressureIndex /*2*/, "Fix PenImc to ask for NormalPressure at index 2!"); if (pressureIndex == -1) { //pressure wasn't found. Add it propertyInfos.Insert(StylusPointDescription.RequiredPressureIndex /*2*/, StylusPointPropertyInfoDefaults.NormalPressure); } _infoX = propertyInfos[0]; _infoY = propertyInfos[1]; _stylusPointDescription = new StylusPointDescription(propertyInfos, pressureIndex); } }
/// <summary> /// Clone with a transform, used by input /// </summary> internal StylusPointCollection Clone(GeneralTransform transform, StylusPointDescription descriptionToUse) { return(this.Clone(transform, descriptionToUse, this.Count)); }
/// <summary> /// Returns a StylusPointCollection object for processing the data in the packet. /// This method creates a new StylusPointCollection and copies the data. /// </summary> public StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetToReformatTo) { return(StylusDeviceImpl.GetStylusPoints(relativeTo, subsetToReformatTo)); }
/// <summary> /// StylusPointCollection /// </summary> public StylusPointCollection() { _stylusPointDescription = new StylusPointDescription(); }
public StylusPointCollection GetStylusPoints(System.Windows.IInputElement relativeTo, StylusPointDescription subsetToReformatTo) { return(default(StylusPointCollection)); }
/// <summary> /// Helper that transforms and scales in one go /// </summary> internal StylusPointCollection Reformat(StylusPointDescription subsetToReformatTo, GeneralTransform transform) { if (!subsetToReformatTo.IsSubsetOf(this.Description)) { throw new ArgumentException(SR.Get(SRID.InvalidStylusPointDescriptionSubset), "subsetToReformatTo"); } StylusPointDescription subsetToReformatToWithCurrentMetrics = StylusPointDescription.GetCommonDescription(subsetToReformatTo, this.Description); //preserve metrics from this spd if (StylusPointDescription.AreCompatible(this.Description, subsetToReformatToWithCurrentMetrics) && (transform is Transform) && ((Transform)transform).IsIdentity) { //subsetToReformatTo might have different x, y, p metrics return(this.Clone(transform, subsetToReformatToWithCurrentMetrics)); } // // we really need to reformat this... // StylusPointCollection newCollection = new StylusPointCollection(subsetToReformatToWithCurrentMetrics, this.Count); int additionalDataCount = subsetToReformatToWithCurrentMetrics.GetExpectedAdditionalDataCount(); ReadOnlyCollection <StylusPointPropertyInfo> properties = subsetToReformatToWithCurrentMetrics.GetStylusPointProperties(); bool isIdentity = (transform is Transform) ? ((Transform)transform).IsIdentity : false; for (int i = 0; i < this.Count; i++) { StylusPoint stylusPoint = this[i]; double xCoord = stylusPoint.X; double yCoord = stylusPoint.Y; float pressure = stylusPoint.GetUntruncatedPressureFactor(); if (!isIdentity) { Point p = new Point(xCoord, yCoord); transform.TryTransform(p, out p); xCoord = p.X; yCoord = p.Y; } int[] newData = null; if (additionalDataCount > 0) { //don't init, we'll do that below newData = new int[additionalDataCount]; } StylusPoint newStylusPoint = new StylusPoint(xCoord, yCoord, pressure, subsetToReformatToWithCurrentMetrics, newData, false, false); //start at 3, skipping x, y, pressure for (int x = StylusPointDescription.RequiredCountOfProperties /*3*/; x < properties.Count; x++) { int value = stylusPoint.GetPropertyValue(properties[x]); newStylusPoint.SetPropertyValue(properties[x], value, false /*copy on write*/); } //bypass validation ((List <StylusPoint>)newCollection.Items).Add(newStylusPoint); } return(newCollection); }
/// <summary> /// Returns a new StylusPointDescription with the common StylusPointProperties from both /// </summary> /// <param name="stylusPointDescription">stylusPointDescription</param> /// <param name="stylusPointDescriptionPreserveInfo">stylusPointDescriptionPreserveInfo</param> /// <remarks>The StylusPointProperties from stylusPointDescriptionPreserveInfo will be returned in the new StylusPointDescription</remarks> public static StylusPointDescription GetCommonDescription(StylusPointDescription stylusPointDescription, StylusPointDescription stylusPointDescriptionPreserveInfo) { if (stylusPointDescription == null) { throw new ArgumentNullException("stylusPointDescription"); } if (stylusPointDescriptionPreserveInfo == null) { throw new ArgumentNullException("stylusPointDescriptionPreserveInfo"); } #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null. // // ignore X, Y, Pressure - they are guaranteed to be the first3 members // Debug.Assert(stylusPointDescription._stylusPointPropertyInfos.Length >= 3 && stylusPointDescription._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); Debug.Assert(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length >= 3 && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); //add x, y, p List<StylusPointPropertyInfo> commonProperties = new List<StylusPointPropertyInfo>(); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0]); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1]); commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2]); //add common properties for (int x = RequiredCountOfProperties; x < stylusPointDescription._stylusPointPropertyInfos.Length; x++) { for (int y = RequiredCountOfProperties; y < stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length; y++) { if (StylusPointPropertyInfo.AreCompatible( stylusPointDescription._stylusPointPropertyInfos[x], stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y])) { commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y]); } } } #pragma warning restore 6506 return new StylusPointDescription(commonProperties); }
public StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetReformatTo) { throw new NotImplementedException(); }
/// <summary> /// Loads packets from the input stream. For example, packets are all of the x's in a stroke /// </summary> #endif static uint LoadPackets(Stream inputStream, uint totalBytesInStrokeBlockOfIsfStream, #if OLD_ISF Compressor compressor, #endif StylusPointDescription stylusPointDescription, Matrix transform, out StylusPointCollection stylusPoints) { stylusPoints = null; if (0 == totalBytesInStrokeBlockOfIsfStream) return 0; uint locallyDecodedBytesRemaining = totalBytesInStrokeBlockOfIsfStream; uint localBytesRead; // First read the no of packets uint pointCount; localBytesRead = SerializationHelper.Decode(inputStream, out pointCount); if (locallyDecodedBytesRemaining < localBytesRead) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); locallyDecodedBytesRemaining -= localBytesRead; if (0 == locallyDecodedBytesRemaining) return localBytesRead; // Allocate packet properties int intsPerPoint = stylusPointDescription.GetInputArrayLengthPerPoint(); int buttonCount = stylusPointDescription.ButtonCount; int buttonIntsPerPoint = (buttonCount > 0 ? 1 : 0); int valueIntsPerPoint = intsPerPoint - buttonIntsPerPoint; //add one int per point for button data if it exists int[] rawPointData = new int[pointCount * intsPerPoint]; int[] packetDataSet = new int[pointCount]; // copy the rest of the data from the stroke data byte[] inputBuffer = new byte[locallyDecodedBytesRemaining]; // Read the input data into the byte array uint bytesRead = StrokeCollectionSerializer.ReliableRead(inputStream, inputBuffer, locallyDecodedBytesRemaining); if ( bytesRead != locallyDecodedBytesRemaining ) { // Make sure the bytes read are expected. If not, we should bail out. // An exception will be thrown. throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); } // at this point, we have read all of the bytes remaining in the input // stream's packet block, and while we will keep the bytes remaining // variable for positioning within the local byte buffer, we should // not read from the stream again, or we risk reading into another // ISF tag's block. int originalPressureIndex = stylusPointDescription.OriginalPressureIndex; for (int i = 0; i < valueIntsPerPoint && locallyDecodedBytesRemaining > 0; i++) { localBytesRead = locallyDecodedBytesRemaining; Compressor.DecompressPacketData( #if OLD_ISF compressor, #endif inputBuffer, ref localBytesRead, packetDataSet); if (localBytesRead > locallyDecodedBytesRemaining) throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF data")); // // packetDataSet is like this: // ------------- // |X|X|X|X|X|X| // ------------- // // we need to copy into rawPointData at // // ------------- // |X| |X| |X| | // ------------- // // additionally, for NormalPressure, if it exists and was // reordered in the StylusPointDescription, we need to account for that here // int tempi = i; if (tempi > 1 && originalPressureIndex != -1 && originalPressureIndex != StylusPointDescription.RequiredPressureIndex/*2*/) { // // NormalPressure exists in the packet stream and was not at index 2 // StylusPointDescription enforces that NormalPressure is at index 2 // so we need to copy packet data beyond X and Y into a different location // // take the example of the original StylusPointDescription // |X|Y|XTilt|YTilt|NormalPressure|Rotation| // // originalPressureIndex is 4, and we know it is now 2 // which means that everything before index 4 has been shifted one // and everything after index 4 is still good. Index 4 should be copied to index 2 if (tempi == originalPressureIndex) { tempi = 2; } else if (tempi < originalPressureIndex) { tempi++; } } locallyDecodedBytesRemaining -= localBytesRead; for (int j = 0, x = 0; j < pointCount; j++, x += intsPerPoint) { rawPointData[x + tempi] = packetDataSet[j]; } // Move the array elements to point to next set of compressed data for (uint u = 0; u < locallyDecodedBytesRemaining; u++) { inputBuffer[u] = inputBuffer[u + (int)localBytesRead]; } } // Now that we've read packet data, we must read button data if it is there byte[] buttonData = null; // since the button state is a simple bit value (either down or up), the button state // for a series of packets is packed into an array of bits rather than integers // For example, if there are 16 packets, and 2 buttons, then 32 bits can be used (e.g. 1 32-bit integer) if (0 != locallyDecodedBytesRemaining && buttonCount > 0) { // calculate the number of full bytes used for buttons per packet // Example: 10 buttons would require 1 full byte int fullBytesForButtonsPerPacket = buttonCount / Native.BitsPerByte; // calculate the number of bits that spill beyond the full byte boundary // Example: 10 buttons would require 2 extra bits (8 fit in a full byte) int partialBitsForButtonsPerPacket = buttonCount % Native.BitsPerByte; // Now figure out how many bytes we need to read for the button data localBytesRead = (uint)((buttonCount * pointCount + 7) / Native.BitsPerByte); if (localBytesRead > locallyDecodedBytesRemaining) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Buffer range is smaller than expected expected size")); } locallyDecodedBytesRemaining -= localBytesRead; int buttonSizeInBytes = (buttonCount + 7)/Native.BitsPerByte; buttonData = new byte[pointCount * buttonSizeInBytes]; // Create a bit reader to unpack the bits from the ISF stream into // loosely packed byte buffer (e.g. button data aligned on full byte // boundaries only) BitStreamReader bitReader = new BitStreamReader(inputBuffer, (uint)buttonCount * pointCount); // unpack the button data into each packet int byteCounter = 0; while (!bitReader.EndOfStream) { // unpack the fully bytes first for (int fullBytes = 0; fullBytes < fullBytesForButtonsPerPacket; fullBytes++) { buttonData[byteCounter++] = bitReader.ReadByte(Native.BitsPerByte); } // then unpack a single partial byte if necessary if (partialBitsForButtonsPerPacket > 0) { buttonData[byteCounter++] = bitReader.ReadByte((int)partialBitsForButtonsPerPacket); } } // if the number of bytes allocated != necessary byte amount then an error occurred if (byteCounter != buttonData.Length) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Button data length not equal to expected length")); } // // set the point data in the raw array // FillButtonData( (int)pointCount, buttonCount, valueIntsPerPoint, //gives the first button index rawPointData, buttonData); } stylusPoints = new StylusPointCollection(stylusPointDescription, rawPointData, null, transform); // if we read too far into the stream (e.g. the packets were compressed) // then move the stream pointer back to the end of the actual packet // data before returning. This keeps the return value on the function // (representing bytes read) honest and consistent with the stream // position movement in this function. if (0 != locallyDecodedBytesRemaining) { inputStream.Seek(0 - (long)locallyDecodedBytesRemaining, SeekOrigin.Current); } return totalBytesInStrokeBlockOfIsfStream - locallyDecodedBytesRemaining; }
///////////////////////////////////////////////////////////////////// /// <summary> /// Returns a StylusPointCollection for processing the data from input. /// This method creates a new StylusPointCollection and copies the data. /// </summary> public StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetToReformatTo) { return StylusDevice.GetStylusPoints(relativeTo, subsetToReformatTo); }
/// <summary> /// StylusPoint /// </summary> /// <param name="x">x</param> /// <param name="y">y</param> /// <param name="pressureFactor">pressureFactor</param> /// <param name="stylusPointDescription">stylusPointDescription</param> /// <param name="additionalValues">additionalValues</param> public StylusPoint(double x, double y, float pressureFactor, StylusPointDescription stylusPointDescription, int[] additionalValues) : this(x, y, pressureFactor, stylusPointDescription, additionalValues, true, true) { }
/// <summary> /// Returns a StylusPointCollection object for processing the data in the packet. /// This method creates a new StylusPointCollection and copies the data. /// </summary> internal abstract StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetToReformatTo);
/// <summary> /// internal ctor /// </summary> 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 <StylusPointPropertyInfo> 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*/); } } } }
///////////////////////////////////////////////////////////////////// /// <summary> /// Returns a StylusPointCollection object for processing the data in the packet. /// This method creates a new StylusPointCollection and copies the data. /// </summary> public StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetToReformatTo) { if (null == subsetToReformatTo) { throw new ArgumentNullException("subsetToReformatTo"); } // Fake up an empty one if we have to. if (_eventStylusPoints == null) { return new StylusPointCollection(subsetToReformatTo); } return _eventStylusPoints.Reformat(subsetToReformatTo, GetElementTransform(relativeTo)); }
private void GetPacketData ( Stroke stroke, out MS.Win32.Recognizer.PACKET_DESCRIPTION packetDescription, out int countOfBytes, out IntPtr packets, out NativeMethods.XFORM xForm ) { int i; countOfBytes = 0; packets = IntPtr.Zero; packetDescription = new MS.Win32.Recognizer.PACKET_DESCRIPTION(); Matrix matrix = Matrix.Identity; xForm = new NativeMethods.XFORM((float)(matrix.M11), (float)(matrix.M12), (float)(matrix.M21), (float)(matrix.M22), (float)(matrix.OffsetX), (float)(matrix.OffsetY)); StylusPointCollection stylusPoints = stroke.StylusPoints; if (stylusPoints.Count == 0) { return; //we'll fail when the calling routine sees that packets is IntPtr.Zer } if (stylusPoints.Description.PropertyCount > StylusPointDescription.RequiredCountOfProperties) { // // reformat to X, Y, P // StylusPointDescription reformatDescription = new StylusPointDescription( new StylusPointPropertyInfo[]{ new StylusPointPropertyInfo(StylusPointProperties.X), new StylusPointPropertyInfo(StylusPointProperties.Y), stylusPoints.Description.GetPropertyInfo(StylusPointProperties.NormalPressure)}); stylusPoints = stylusPoints.Reformat(reformatDescription); } // // now make sure we only take a finite amount of data for the stroke // if (stylusPoints.Count > MaxStylusPoints) { stylusPoints = stylusPoints.Clone(MaxStylusPoints); } Guid[] propertyGuids = new Guid[]{ StylusPointPropertyIds.X, //required index for SPD StylusPointPropertyIds.Y, //required index for SPD StylusPointPropertyIds.NormalPressure}; //required index for SPD Debug.Assert(stylusPoints != null); Debug.Assert(propertyGuids.Length == StylusPointDescription.RequiredCountOfProperties); // Get the packet description packetDescription.cbPacketSize = (uint)(propertyGuids.Length * Marshal.SizeOf(typeof(Int32))); packetDescription.cPacketProperties = (uint)propertyGuids.Length; // // use X, Y defaults for metrics, sometimes mouse metrics can be bogus // always use NormalPressure metrics, though. // StylusPointPropertyInfo[] infosToUse = new StylusPointPropertyInfo[StylusPointDescription.RequiredCountOfProperties]; infosToUse[StylusPointDescription.RequiredXIndex] = StylusPointPropertyInfoDefaults.X; infosToUse[StylusPointDescription.RequiredYIndex] = StylusPointPropertyInfoDefaults.Y; infosToUse[StylusPointDescription.RequiredPressureIndex] = stylusPoints.Description.GetPropertyInfo(StylusPointProperties.NormalPressure); MS.Win32.Recognizer.PACKET_PROPERTY[] packetProperties = new MS.Win32.Recognizer.PACKET_PROPERTY[packetDescription.cPacketProperties]; StylusPointPropertyInfo propertyInfo; for ( i = 0; i < packetDescription.cPacketProperties; i++ ) { packetProperties[i].guid = propertyGuids[i]; propertyInfo = infosToUse[i]; MS.Win32.Recognizer.PROPERTY_METRICS propertyMetrics = new MS.Win32.Recognizer.PROPERTY_METRICS( ); propertyMetrics.nLogicalMin = propertyInfo.Minimum; propertyMetrics.nLogicalMax = propertyInfo.Maximum; propertyMetrics.Units = (int)(propertyInfo.Unit); propertyMetrics.fResolution = propertyInfo.Resolution; packetProperties[i].PropertyMetrics = propertyMetrics; } unsafe { int allocationSize = (int)(Marshal.SizeOf(typeof(MS.Win32.Recognizer.PACKET_PROPERTY)) * packetDescription.cPacketProperties); packetDescription.pPacketProperties = Marshal.AllocCoTaskMem(allocationSize); MS.Win32.Recognizer.PACKET_PROPERTY* pPacketProperty = (MS.Win32.Recognizer.PACKET_PROPERTY*)(packetDescription.pPacketProperties.ToPointer()); MS.Win32.Recognizer.PACKET_PROPERTY* pElement = pPacketProperty; for ( i = 0 ; i < packetDescription.cPacketProperties ; i ++ ) { Marshal.StructureToPtr(packetProperties[i], new IntPtr(pElement), false); pElement++; } } // Get packet data int[] rawPackets = stylusPoints.ToHiMetricArray(); int packetCount = rawPackets.Length; if (packetCount != 0) { countOfBytes = packetCount * Marshal.SizeOf(typeof(Int32)); packets = Marshal.AllocCoTaskMem(countOfBytes); Marshal.Copy(rawPackets, 0, packets, packetCount); } }
private void InitStylusPointDescription() { int cProps; int cButtons; int pressureIndex = -1; // Make sure we are never called on the application thread when we need to talk // to penimc or else we can cause reentrancy! Debug.Assert(!_contexts._inputSource.Value.CheckAccess()); // We should always have a valid IPimcContext2 interface pointer. Debug.Assert(_pimcContext != null && _pimcContext.Value != null); _pimcContext.Value.GetPacketDescriptionInfo(out cProps, out cButtons); // Calls Unmanaged code - SecurityCritical with SUC. List <StylusPointPropertyInfo> propertyInfos = new List <StylusPointPropertyInfo>(cProps + cButtons + 3); for (int i = 0; i < cProps; i++) { Guid guid; int min, max; int units; float res; _pimcContext.Value.GetPacketPropertyInfo(i, out guid, out min, out max, out units, out res); // Calls Unmanaged code - SecurityCritical with SUC. if (pressureIndex == -1 && guid == StylusPointPropertyIds.NormalPressure) { pressureIndex = i; } if (_statusPropertyIndex == -1 && guid == StylusPointPropertyIds.PacketStatus) { _statusPropertyIndex = i; } StylusPointPropertyInfo propertyInfo = new StylusPointPropertyInfo(new StylusPointProperty(guid, false), min, max, (StylusPointPropertyUnit)units, res); propertyInfos.Add(propertyInfo); } Debug.Assert(_statusPropertyIndex != -1); // We should always see this. // Make sure we actually created propertyInfos OK if (propertyInfos != null) { for (int i = 0; i < cButtons; i++) { Guid buttonGuid; _pimcContext.Value.GetPacketButtonInfo(i, out buttonGuid); // Calls Unmanaged code - SecurityCritical with SUC. StylusPointProperty buttonProperty = new StylusPointProperty(buttonGuid, true); StylusPointPropertyInfo buttonInfo = new StylusPointPropertyInfo(buttonProperty); propertyInfos.Add(buttonInfo); } //validate we can never get X, Y at index != 0, 1 Debug.Assert(propertyInfos[StylusPointDescription.RequiredXIndex /*0*/].Id == StylusPointPropertyIds.X, "X isn't where we expect it! Fix PenImc to ask for X at index 0"); Debug.Assert(propertyInfos[StylusPointDescription.RequiredYIndex /*0*/].Id == StylusPointPropertyIds.Y, "Y isn't where we expect it! Fix PenImc to ask for Y at index 1"); Debug.Assert(pressureIndex == -1 || pressureIndex == StylusPointDescription.RequiredPressureIndex /*2*/, "Fix PenImc to ask for NormalPressure at index 2!"); if (pressureIndex == -1) { //pressure wasn't found. Add it propertyInfos.Insert(StylusPointDescription.RequiredPressureIndex /*2*/, StylusPointPropertyInfoDefaults.NormalPressure); } _infoX = propertyInfos[0]; _infoY = propertyInfos[1]; _stylusPointDescription = new StylusPointDescription(propertyInfos, pressureIndex); } }
/// <summary> /// Returns true if the two StylusPointDescriptions have the same StylusPointProperties. Metrics are ignored. /// </summary> /// <param name="stylusPointDescription1">stylusPointDescription1</param> /// <param name="stylusPointDescription2">stylusPointDescription2</param> public static bool AreCompatible(StylusPointDescription stylusPointDescription1, StylusPointDescription stylusPointDescription2) { if (stylusPointDescription1 == null || stylusPointDescription2 == null) { throw new ArgumentNullException("stylusPointDescription"); } #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null. // // ignore X, Y, Pressure - they are guaranteed to be the first3 members // Debug.Assert( stylusPointDescription1._stylusPointPropertyInfos.Length >= RequiredCountOfProperties && stylusPointDescription1._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription1._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription1._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); Debug.Assert( stylusPointDescription2._stylusPointPropertyInfos.Length >= RequiredCountOfProperties && stylusPointDescription2._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X && stylusPointDescription2._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y && stylusPointDescription2._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure); if (stylusPointDescription1._stylusPointPropertyInfos.Length != stylusPointDescription2._stylusPointPropertyInfos.Length) { return false; } for (int x = RequiredCountOfProperties; x < stylusPointDescription1._stylusPointPropertyInfos.Length; x++) { if (!StylusPointPropertyInfo.AreCompatible(stylusPointDescription1._stylusPointPropertyInfos[x], stylusPointDescription2._stylusPointPropertyInfos[x])) { return false; } } #pragma warning restore 6506 return true; }