public bool IsEqual(StrokeDescriptor strd) { // If the no of templates in them are different return false if( _strokeDescriptor.Count != strd.Template.Count ) return false; // Compare each tag in the template. If any one of them is different, return false; for( int i = 0; i < _strokeDescriptor.Count; i++ ) if( _strokeDescriptor[i] != strd.Template[i] ) return false; return true; }
public bool IsEqual(StrokeDescriptor strd) { // If the no of templates in them are different return false if (_strokeDescriptor.Count != strd.Template.Count) { return(false); } // Compare each tag in the template. If any one of them is different, return false; for (int i = 0; i < _strokeDescriptor.Count; i++) { if (_strokeDescriptor[i] != strd.Template[i]) { return(false); } } return(true); }
/// <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="compressor">Compression module</param> /// <param name="stroke">Newly decoded stroke</param> /// <returns></returns> #else /// <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> /// 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> /// Builds the Stroke Descriptor for this stroke based on Packet Layout and Extended Properties /// For details on how this is strored please refer to the spec. /// </summary> internal static void BuildStrokeDescriptor( Stroke stroke, GuidList guidList, StrokeCollectionSerializer.StrokeLookupEntry strokeLookupEntry, out StrokeDescriptor strokeDescriptor, out MetricBlock metricBlock) { // Initialize the metric block for this stroke metricBlock = new MetricBlock(); // Clear any existing template strokeDescriptor = new StrokeDescriptor(); // Uninitialized variable passed in AddMetricEntry MetricEntryType metricEntryType; StylusPointDescription stylusPointDescription = stroke.StylusPoints.Description; KnownTagCache.KnownTagIndex tag = guidList.FindTag(KnownIds.X, true); metricEntryType = metricBlock.AddMetricEntry(stylusPointDescription.GetPropertyInfo(StylusPointProperties.X), tag); tag = guidList.FindTag(KnownIds.Y, true); metricEntryType = metricBlock.AddMetricEntry(stylusPointDescription.GetPropertyInfo(StylusPointProperties.Y), tag); ReadOnlyCollection <StylusPointPropertyInfo> propertyInfos = stylusPointDescription.GetStylusPointProperties(); int i = 0; //i is defined out of the for loop so we can use it later for buttons for (i = 2 /*past x,y*/; i < propertyInfos.Count; i++) { if (i == /*StylusPointDescription.RequiredPressureIndex //修复构建的代码 */ 2 && !strokeLookupEntry.StorePressure) { // // don't store pressure information // continue; } StylusPointPropertyInfo propertyInfo = propertyInfos[i]; if (propertyInfo.IsButton) { //we don't serialize buttons break; } tag = guidList.FindTag(propertyInfo.Id, true); strokeDescriptor.Template.Add(tag); strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); // Create the MetricEntry for this property if necessary metricEntryType = metricBlock.AddMetricEntry(propertyInfo, tag); } /* * we drop button data on the floor. * int buttonCount = stylusPointDescription.ButtonCount; * // Now write the button tags in the Template * if (buttonCount > 0) * { * // First write the TAG_BUTTONS * strokeDescriptor.Template.Add(KnownTagCache.KnownTagIndex.Buttons); * strokeDescriptor.Size += SerializationHelper.VarSize((uint)KnownTagCache.KnownTagIndex.Buttons); * * // Next write the i of buttons * strokeDescriptor.Template.Add((KnownTagCache.KnownTagIndex)buttonCount); * strokeDescriptor.Size += SerializationHelper.VarSize((uint)buttonCount); * * //we broke above on i when it was a button, it still * //points to the first button * for (; i < propertyInfos.Count; i++) * { * StylusPointPropertyInfo propertyInfo = propertyInfos[i]; * tag = guidList.FindTag(propertyInfo.Id, false); * * strokeDescriptor.Template.Add(tag); * strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); * } * } */ // Now write the extended properties in the template if (stroke.ExtendedProperties.Count > 0) { strokeDescriptor.Template.Add(KnownTagCache.KnownTagIndex.StrokePropertyList); strokeDescriptor.Size += SerializationHelper.VarSize((uint)KnownTagCache.KnownTagIndex.StrokePropertyList); // Now write the tags corresponding to each extended properties of the stroke for (int x = 0; x < stroke.ExtendedProperties.Count; x++) { tag = guidList.FindTag(stroke.ExtendedProperties[(int)x].Id, false); strokeDescriptor.Template.Add(tag); strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); } } }
/// <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="compressor"></param> /// <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> /// <returns></returns> #else /// <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); }
/// <summary> /// Reads and Decodes a stroke descriptor information from the stream. For details on how it is stored /// please refer the spec /// </summary> /// <param name="strm"></param> /// <param name="cbSize"></param> /// <param name="descr"></param> /// <returns></returns> private uint DecodeStrokeDescriptor(Stream strm, uint cbSize, out StrokeDescriptor descr) { descr = new StrokeDescriptor(); if (0 == cbSize) return 0; uint cb; uint cbBlock = cbSize; while (cbBlock > 0) { // first read the tag KnownTagCache.KnownTagIndex tag; uint uiTag; cb = SerializationHelper.Decode(strm, out uiTag); tag = (KnownTagCache.KnownTagIndex)uiTag; if (cb > cbBlock) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbBlock -= cb; descr.Template.Add(tag); // If this is TAG_BUTTONS if (KnownTagCache.KnownTagIndex.Buttons == tag && cbBlock > 0) { uint cbButton; // Read the no. of buttons first cb = SerializationHelper.Decode(strm, out cbButton); if (cb > cbBlock) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbBlock -= cb; descr.Template.Add((KnownTagCache.KnownTagIndex)cbButton); while (cbBlock > 0 && cbButton > 0) { uint dw; cb = SerializationHelper.Decode(strm, out dw); if (cb > cbBlock) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbBlock -= cb; cbButton--; descr.Template.Add((KnownTagCache.KnownTagIndex)dw); } } else if (KnownTagCache.KnownTagIndex.StrokePropertyList == tag && cbBlock > 0) { // Usually stroke property comes last in the template. Hence everything below this is // are Tags for strokes extended properties while (cbBlock > 0) { uint dw; cb = SerializationHelper.Decode(strm, out dw); if (cb > cbBlock) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbBlock -= cb; descr.Template.Add((KnownTagCache.KnownTagIndex)dw); } } } if (0 != cbBlock) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); return cbSize; }
/// <summary> /// Multibyte Encodes a Stroke Descroptor /// </summary> /// <param name="strm"></param> /// <param name="strd"></param> /// <returns></returns> private uint EncodeStrokeDescriptor(Stream strm, StrokeDescriptor strd) { uint cbData = 0; // First encode the size of the descriptor cbData += SerializationHelper.Encode(strm, strd.Size); for (int count = 0; count < strd.Template.Count; count++) { // Now encode all members of the descriptor cbData += SerializationHelper.Encode(strm, (uint)strd.Template[count]); } return cbData; }
/// <summary> /// Builds StylusPointDescription based on StrokeDescriptor and Metric Descriptor Block. Sometime Metric Descriptor block may contain /// metric information for properties which are not part of the stroke descriptor. They are simply ignored. /// </summary> /// <param name="strd"></param> /// <param name="block"></param> /// <param name="guidList"></param> /// <returns></returns> private StylusPointDescription BuildStylusPointDescription(StrokeDescriptor strd, MetricBlock block, GuidList guidList) { int cTags = 0; int packetPropertyCount = 0; uint buttonCount = 0; Guid[] buttonguids = null; System.Collections.Generic.List<KnownTagCache.KnownTagIndex> tags = null; // if strd is null, it means there is only default descriptor with X & Y if (null != strd) { tags = new System.Collections.Generic.List<KnownTagCache.KnownTagIndex>(); while (cTags < strd.Template.Count) { KnownTagCache.KnownTagIndex tag = (KnownTagCache.KnownTagIndex)strd.Template[cTags]; if (KnownTagCache.KnownTagIndex.Buttons == tag) { cTags++; // The next item in the array is no of buttongs. buttonCount = (uint)strd.Template[cTags]; cTags++; // Currently we skip the the no of buttons as buttons is not implimented yet buttonguids = new Guid[buttonCount]; for (uint u = 0; u < buttonCount; u++) { Guid guid = guidList.FindGuid(strd.Template[cTags]); if (guid == Guid.Empty) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Button guid tag embedded in ISF stream does not match guid table"),"strd"); } buttonguids[(int)u] = guid; cTags++; } } else if (KnownTagCache.KnownTagIndex.StrokePropertyList == tag) { break; // since no more Packet properties can be stored } else { if (KnownTagCache.KnownTagIndex.NoX == tag || KnownTagCache.KnownTagIndex.NoY == tag) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Invalid ISF with NoX or NoY specified"), "strd"); } tags.Add(strd.Template[cTags]); packetPropertyCount++; cTags++; } } } List<StylusPointPropertyInfo> stylusPointPropertyInfos = new List<StylusPointPropertyInfo>(); stylusPointPropertyInfos.Add(GetStylusPointPropertyInfo(KnownIds.X, (KnownTagCache.KnownTagIndex)((uint)KnownIdCache.KnownGuidBaseIndex + (uint)KnownIdCache.OriginalISFIdIndex.X), block)); stylusPointPropertyInfos.Add(GetStylusPointPropertyInfo(KnownIds.Y, (KnownTagCache.KnownTagIndex)((uint)KnownIdCache.KnownGuidBaseIndex + (uint)KnownIdCache.OriginalISFIdIndex.Y), block)); stylusPointPropertyInfos.Add(GetStylusPointPropertyInfo(KnownIds.NormalPressure, (KnownTagCache.KnownTagIndex)((uint)KnownIdCache.KnownGuidBaseIndex + (uint)KnownIdCache.OriginalISFIdIndex.NormalPressure), block)); int pressureIndex = -1; if (tags != null) { for (int i = 0; i < tags.Count; i++) { Guid guid = guidList.FindGuid(tags[i]); if (guid == Guid.Empty) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Packet Description Property tag embedded in ISF stream does not match guid table"), "strd"); } if (pressureIndex == -1 && guid == StylusPointPropertyIds.NormalPressure) { pressureIndex = i + 2; //x,y have already been accounted for continue; //we've already added pressure (above) } stylusPointPropertyInfos.Add(GetStylusPointPropertyInfo(guid, tags[i], block)); } if (null != buttonguids) { // // add the buttons to the end of the description if they exist // for (int i = 0; i < buttonguids.Length; i++) { StylusPointProperty buttonProperty = new StylusPointProperty(buttonguids[i], true); StylusPointPropertyInfo buttonInfo = new StylusPointPropertyInfo(buttonProperty); stylusPointPropertyInfos.Add(buttonInfo); } } } return new StylusPointDescription(stylusPointPropertyInfos, pressureIndex); }
/// <summary> /// Builds the Stroke Descriptor for this stroke based on Packet Layout and Extended Properties /// For details on how this is strored please refer to the spec. /// </summary> internal static void BuildStrokeDescriptor( Stroke stroke, GuidList guidList, StrokeCollectionSerializer.StrokeLookupEntry strokeLookupEntry, out StrokeDescriptor strokeDescriptor, out MetricBlock metricBlock) { // Initialize the metric block for this stroke metricBlock = new MetricBlock(); // Clear any existing template strokeDescriptor = new StrokeDescriptor(); // Uninitialized variable passed in AddMetricEntry MetricEntryType metricEntryType; StylusPointDescription stylusPointDescription = stroke.StylusPoints.Description; KnownTagCache.KnownTagIndex tag = guidList.FindTag(KnownIds.X, true); metricEntryType = metricBlock.AddMetricEntry(stylusPointDescription.GetPropertyInfo(StylusPointProperties.X), tag); tag = guidList.FindTag(KnownIds.Y, true); metricEntryType = metricBlock.AddMetricEntry(stylusPointDescription.GetPropertyInfo(StylusPointProperties.Y), tag); ReadOnlyCollection<StylusPointPropertyInfo> propertyInfos = stylusPointDescription.GetStylusPointProperties(); int i = 0; //i is defined out of the for loop so we can use it later for buttons for (i = 2/*past x,y*/; i < propertyInfos.Count; i++) { if (i == StylusPointDescription.RequiredPressureIndex/*2*/ && !strokeLookupEntry.StorePressure) { // // don't store pressure information // continue; } StylusPointPropertyInfo propertyInfo = propertyInfos[i]; if (propertyInfo.IsButton) { //we don't serialize buttons break; } tag = guidList.FindTag(propertyInfo.Id, true); strokeDescriptor.Template.Add(tag); strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); // Create the MetricEntry for this property if necessary metricEntryType = metricBlock.AddMetricEntry(propertyInfo, tag); } /* we drop button data on the floor. See Windows OS Bugs 1413460 for details int buttonCount = stylusPointDescription.ButtonCount; // Now write the button tags in the Template if (buttonCount > 0) { // First write the TAG_BUTTONS strokeDescriptor.Template.Add(KnownTagCache.KnownTagIndex.Buttons); strokeDescriptor.Size += SerializationHelper.VarSize((uint)KnownTagCache.KnownTagIndex.Buttons); // Next write the i of buttons strokeDescriptor.Template.Add((KnownTagCache.KnownTagIndex)buttonCount); strokeDescriptor.Size += SerializationHelper.VarSize((uint)buttonCount); //we broke above on i when it was a button, it still //points to the first button for (; i < propertyInfos.Count; i++) { StylusPointPropertyInfo propertyInfo = propertyInfos[i]; tag = guidList.FindTag(propertyInfo.Id, false); strokeDescriptor.Template.Add(tag); strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); } } */ // Now write the extended properties in the template if (stroke.ExtendedProperties.Count > 0) { strokeDescriptor.Template.Add(KnownTagCache.KnownTagIndex.StrokePropertyList); strokeDescriptor.Size += SerializationHelper.VarSize((uint)KnownTagCache.KnownTagIndex.StrokePropertyList); // Now write the tags corresponding to each extended properties of the stroke for (int x = 0; x < stroke.ExtendedProperties.Count; x++) { tag = guidList.FindTag(stroke.ExtendedProperties[(int)x].Id, false); strokeDescriptor.Template.Add(tag); strokeDescriptor.Size += SerializationHelper.VarSize((uint)tag); } } }
/// <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; }