/// <summary> /// Adds a new metric entry in the existing list of metric entries /// </summary> /// <param name="property"></param> /// <param name="tag"></param> /// <returns></returns> public MetricEntryType AddMetricEntry(StylusPointPropertyInfo property, KnownTagCache.KnownTagIndex tag) { // Create a new metric entry based on the packet information passed. MetricEntry entry = new MetricEntry(); MetricEntryType type = entry.CreateMetricEntry(property, tag); // Don't add this entry to the global list if size is 0, means default metric values! if (0 == entry.Size) { return(type); } MetricEntry start = _Entry; if (null == start) { _Entry = entry; } else // tack on data at the end, want to keep x,y at the beginning { while (start.Next != null) { start = start.Next; } start.Next = entry; } _Count++; _size += entry.Size + SerializationHelper.VarSize(entry.Size) + SerializationHelper.VarSize((uint)_Entry.Tag); return(type); }
/// <summary> /// Adds a new metric entry in the existing list of metric entries /// </summary> /// <param name="newEntry"></param> /// <returns></returns> public void AddMetricEntry(MetricEntry newEntry) { if (null == newEntry) { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("MetricEntry cannot be null")); } if (null == _Entry) { _Entry = newEntry; } else { _Entry.Add(newEntry); // tack on at the end } _Count++; _size += newEntry.Size + SerializationHelper.VarSize(newEntry.Size) + SerializationHelper.VarSize((uint)newEntry.Tag); }
/// <summary> /// Serializes the GuidList in the memory stream and returns the size /// </summary> /// <param name="stream">If null, calculates the size only</param> /// <returns></returns> public uint Save(Stream stream) { // calculate the number of custom guids to persist // custom guids are those which are not reserved in ISF via 'tags' uint ul = (uint)(_CustomGuids.Count * Native.SizeOfGuid); // if there are no custom guids, then the guid list can be persisted // without any cost ('tags' are freely storeable) if (ul == 0) { return(0); } // if only the size was requested, return it if (null == stream) { return((uint)(ul + SerializationHelper.VarSize(ul) + SerializationHelper.VarSize((uint)KnownTagCache.KnownTagIndex.GuidTable))); } // encode the guid table tag in the output stream uint cbWrote = SerializationHelper.Encode(stream, (uint)KnownTagCache.KnownTagIndex.GuidTable); // encode the size of the guid table cbWrote += SerializationHelper.Encode(stream, ul); // encode each guid in the table for (int i = 0; i < _CustomGuids.Count; i++) { Guid guid = (Guid)_CustomGuids[i]; stream.Write(guid.ToByteArray(), 0, (int)Native.SizeOfGuid); } cbWrote += ul; return(cbWrote); }
/// <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); } } }