/// <summary> /// Deserializes the GuidList from the memory stream /// </summary> /// <param name="strm"></param> /// <param name="size"></param> /// <returns></returns> public uint Load(Stream strm, uint size) { uint cbsize = 0; _CustomGuids.Clear(); uint count = size / Native.SizeOfGuid; byte[] guids = new byte[Native.SizeOfGuid]; for (uint i = 0; i < count; i++) { // NTRAID:WINDOWSOS#1622775-2006/04/26-WAYNEZEN, // Stream.Read could read less number of bytes than the request. We call ReliableRead that // reads the bytes in a loop until all requested bytes are received or reach the end of the stream. uint bytesRead = StrokeCollectionSerializer.ReliableRead(strm, guids, Native.SizeOfGuid); cbsize += bytesRead; if (bytesRead == Native.SizeOfGuid) { _CustomGuids.Add(new Guid(guids)); } else { // If Stream.Read cannot return the expected number of bytes, we should break here. // The caller - StrokeCollectionSerializer.DecodeRawISF will check our return value. // An exception might be thrown if reading is failed. break; } } return(cbsize); }
/// <summary> /// Loads packets from the input stream. For example, packets are all of the x's in a stroke /// </summary> #else /// <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 = 0; //修复构建的代码 stylusPointDescription.GetInputArrayLengthPerPoint(); int buttonCount = 0; //修复构建的代码 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 = 0; //修复构建的代码 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> /// 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); }