/// <summary> /// Returns an array of bytes of the saved stroke /// </summary> /// <param name="stroke">Stroke to save</param> /// <param name="stream">null to calculate only the size</param> /// <param name="compressor"></param> /// <param name="compressionAlgorithm"></param> /// <param name="guidList"></param> /// <param name="strokeLookupEntry"></param> #else /// <summary> /// Returns an array of bytes of the saved stroke /// </summary> /// <param name="stroke">Stroke to save</param> /// <param name="stream">null to calculate only the size</param> /// <param name="compressionAlgorithm"></param> /// <param name="guidList"></param> /// <param name="strokeLookupEntry"></param> #endif internal static uint EncodeStroke( Stroke stroke, Stream stream, #if OLD_ISF Compressor compressor, #endif byte compressionAlgorithm, GuidList guidList, StrokeCollectionSerializer.StrokeLookupEntry strokeLookupEntry) { uint cbWrite = SavePackets(stroke, stream, #if OLD_ISF compressor, #endif strokeLookupEntry); if (stroke.ExtendedProperties.Count > 0) { cbWrite += ExtendedPropertySerializer.EncodeAsISF(stroke.ExtendedProperties, stream, guidList, compressionAlgorithm, false); } return(cbWrite); }
/// <summary> /// Saves the packets into a stream of bytes /// </summary> /// <param name="stroke">Stroke to save</param> /// <param name="stream">null to calculate size only</param> /// <param name="compressor"></param> /// <param name="strokeLookupEntry"></param> /// <returns></returns> #else /// <summary> /// Saves the packets into a stream of bytes /// </summary> /// <param name="stroke">Stroke to save</param> /// <param name="stream">null to calculate size only</param> /// <param name="strokeLookupEntry"></param> #endif static uint SavePackets( Stroke stroke, Stream stream, #if OLD_ISF Compressor compressor, #endif StrokeCollectionSerializer.StrokeLookupEntry strokeLookupEntry) { // First write or calculate how many points are there uint pointCount = (uint)stroke.StylusPoints.Count; uint localBytesWritten = (stream != null) ? SerializationHelper.Encode(stream, pointCount) : SerializationHelper.VarSize(pointCount); byte compressionAlgorithm; int[][] outputArrays = strokeLookupEntry.ISFReadyStrokeData; //We don't serialize button data //int valuesPerPoint = stroke.StylusPoints.Description.GetOutputArrayLengthPerPoint(); //int buttonCount = stroke.StylusPoints.Description.ButtonCount; ReadOnlyCollection <StylusPointPropertyInfo> propertyInfos = stroke.StylusPoints.Description.GetStylusPointProperties(); int i = 0; for (; i < propertyInfos.Count; i++) { StylusPointPropertyInfo propertyInfo = propertyInfos[i]; if (i == 2 && !strokeLookupEntry.StorePressure) { // // only store pressure if we need to // continue; } if (propertyInfo.IsButton) { // // we're at the buttons, handle this below // break; } compressionAlgorithm = strokeLookupEntry.CompressionData; localBytesWritten += SavePacketPropertyData(outputArrays[i], stream, #if OLD_ISF compressor, #endif propertyInfo.Id, ref compressionAlgorithm); } /* * We don't serialize button data * // Now write all button data. Button data is stored as if it is another packet property * // with size (cbuttoncount + 7)/8 bytes and corresponding guids are stored in the packet * // description. Button data is only stored if buttons are present in the description and there * // are packets in the stroke * if (buttonCount > 0 && pointCount > 0) * { * Debug.Assert(i == valuesPerPoint - 1); * BitStreamWriter bitWriter = new BitStreamWriter(); * // * // Get the array of button data (i is still pointing at it) * // * int[] buttonData = outputArrays[i]; * * for (int x = 0; x < pointCount; x++) * { * // * // each int in the button data array contains buttonCount number * // of bits that need to be written to the BitStreamWriter * // the BitStreamWriter takes bytes at a time. We always write the most * // signifigant bits first * // * int uncompactedButtonDataForPoint = buttonData[x]; * * // calculate the number of full bytes used for buttons per packet * // Example: 10 buttons would require 1 full byte * // but 8 would require * 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 bitsToWrite = buttonCount % Native.BitsPerByte; * * for (; fullBytesForButtonsPerPacket >= 0; fullBytesForButtonsPerPacket--) * { * byte byteOfButtonData = * Convert.ToByte(uncompactedButtonDataForPoint >> (fullBytesForButtonsPerPacket * Native.BitsPerByte)); * // * // write 8 or less bytes to the bitwriter * // checking for 0 handles the case where we're writing 8, 16 or 24 bytes * // and bitsToWrite is initialize to zero * // * if (bitsToWrite > 0) * { * bitWriter.Write(byteOfButtonData, bitsToWrite); * } * if (fullBytesForButtonsPerPacket > 0) * { * bitsToWrite = Native.BitsPerByte; * } * } * } * * // retrieve the button bytes * byte[] packedButtonData = bitWriter.ToBytes(); * * if (packedButtonData.Length != * ((buttonCount * pointCount + 7) / Native.BitsPerByte)) * { * throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Packed button length not equal to expected length")); * } * * // write out the packed button data to the output stream * stream.Write(packedButtonData, 0, packedButtonData.Length); * localBytesWritten += (uint)packedButtonData.Length; * } */ return(localBytesWritten); }
/// <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); } } }