// // /// <summary> /// This function compares pMetricColl with the current one. If pMetricColl has more entries apart from the one /// in the current list with which some of its entries are identical, setType is set as SUPERSET. /// </summary> /// <param name="metricColl"></param> /// <param name="setType"></param> /// <returns></returns> public bool CompareMetricBlock( MetricBlock metricColl, ref SetType setType) { if( null == metricColl ) return false; // if both have null entry, implies default metric Block for both of them // and it already exists in the list. Return TRUE // If only one of the blocks is empty, return FALSE - they cannot be merged // because the other block may have customized GUID_X or GUID_Y. if (null == GetMetricEntryList()) return (metricColl.GetMetricEntryList() == null); if (null == metricColl.GetMetricEntryList()) return false; // Else compare the entries bool fTagFound = false; uint cbLhs = this.MetricEntryCount; // No of entries in this block uint cbRhs = metricColl.MetricEntryCount; // No of entries in the block to be compared MetricEntry outside, inside; if( metricColl.MetricEntryCount <= MetricEntryCount ) { outside = metricColl.GetMetricEntryList(); inside = GetMetricEntryList(); } else { inside = metricColl.GetMetricEntryList(); outside = GetMetricEntryList(); setType = SetType.SuperSet; } // For each entry in metricColl, search for the same in this Block. // If it is found, continue with the next entry of smaller Block. while( null != outside ) { fTagFound = false; // Always start at the begining of the larger block MetricEntry temp = inside; while( null != temp ) { if( outside.Compare(temp) ) { fTagFound = true; break; } else temp = temp.Next; } if( !fTagFound ) return false; // Found the entry; Continue with the next entry in the outside block outside = outside.Next; } return true; }
/// <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> /// 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> /// Sets the Property Metrics for a property based on Tag and metric descriptor block /// </summary> /// <param name="guid"></param> /// <param name="tag"></param> /// <param name="block"></param> /// <returns></returns> private StylusPointPropertyInfo GetStylusPointPropertyInfo(Guid guid, KnownTagCache.KnownTagIndex tag, MetricBlock block) { int dw = 0; bool fSetDefault = false; uint cbEntry; // StylusPointPropertyInfo values that we need to read in. int minimum = 0; int maximum = 0; StylusPointPropertyUnit unit = StylusPointPropertyUnit.None; float resolution = 1.0f; // To begin with initialize the property metrics with respective default valuses // first check if this property belongs to optional list for (dw = 0; dw < 11; dw++) { if (MetricEntry.MetricEntry_Optional[dw].Tag == tag) { minimum = MetricEntry.MetricEntry_Optional[dw].PropertyMetrics.Minimum; maximum = MetricEntry.MetricEntry_Optional[dw].PropertyMetrics.Maximum; resolution = MetricEntry.MetricEntry_Optional[dw].PropertyMetrics.Resolution; unit = MetricEntry.MetricEntry_Optional[dw].PropertyMetrics.Unit; fSetDefault = true; break; } } if (false == fSetDefault) { // We will come here if the property is not found in the Optional List // All other cases, we will have only default values minimum = Int32.MinValue; maximum = Int32.MaxValue; unit = StylusPointPropertyUnit.None; resolution = 1.0f; fSetDefault = true; } // Now see if there is a valid MetricBlock. If there is one, update the PROPERTY_METRICS with // values from this Block if (null != block) { MetricEntry entry = block.GetMetricEntryList(); while (null != entry) { if (entry.Tag == tag) { cbEntry = 0; int range; using (MemoryStream strm = new MemoryStream(entry.Data)) { // Decoded the Logical Min cbEntry += SerializationHelper.SignDecode(strm, out range); if (cbEntry >= entry.Size) { break; // return false; } minimum = range; // Logical Max cbEntry += SerializationHelper.SignDecode(strm, out range); if (cbEntry >= entry.Size) { break; // return false; } maximum = range; uint cb; // Units cbEntry += SerializationHelper.Decode(strm, out cb); unit = (StylusPointPropertyUnit)cb; if (cbEntry >= entry.Size) { break; // return false; } using (BinaryReader br = new BinaryReader(strm)) { resolution = br.ReadSingle(); cbEntry += Native.SizeOfFloat; } } break; } entry = entry.Next; } } // return a new StylusPointPropertyInfo return new StylusPointPropertyInfo( new StylusPointProperty(guid, StylusPointPropertyIds.IsKnownButton(guid)), minimum, maximum, unit, resolution); }
/// <summary> /// Decodes a Metric Block from the stream. For information on how they are stored in the stream, please refer to the spec. /// </summary> /// <param name="strm"></param> /// <param name="cbSize"></param> /// <param name="block"></param> /// <returns></returns> private uint DecodeMetricBlock(Stream strm, uint cbSize, out MetricBlock block) { // allocate the block block = new MetricBlock(); if (cbSize == 0) return 0; uint cb; uint cbTotal = cbSize; uint size; while (cbTotal > 0) { // First decode the tag for this entry uint dw; cb = SerializationHelper.Decode(strm, out dw); if (cb > cbTotal) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbTotal -= cb; // Next read the size of the metric data cb = SerializationHelper.Decode(strm, out size); if (cb + size > cbTotal) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); cbTotal -= cb; // now create new metric entry MetricEntry entry = new MetricEntry(); entry.Tag = (KnownTagCache.KnownTagIndex)dw; byte[] data = new byte[size]; uint bytesRead = StrokeCollectionSerializer.ReliableRead(strm, data, size); cbTotal -= bytesRead; if ( bytesRead != size ) { // Make sure the bytes read are expected. If not, we should bail out. // An exception will be thrown. break; } entry.Data = data; block.AddMetricEntry(entry); } if (0 != cbTotal) throw new ArgumentException(ISFDebugMessage("Invalid ISF data"),"strm"); return cbSize; }
/// <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 function compares pMetricColl with the current one. If pMetricColl has more entries apart from the one /// in the current list with which some of its entries are identical, setType is set as SUPERSET. /// </summary> /// <param name="metricColl"></param> /// <param name="setType"></param> /// <returns></returns> public bool CompareMetricBlock(MetricBlock metricColl, ref SetType setType) { if (null == metricColl) { return(false); } // if both have null entry, implies default metric Block for both of them // and it already exists in the list. Return TRUE // If only one of the blocks is empty, return FALSE - they cannot be merged // because the other block may have customized GUID_X or GUID_Y. if (null == GetMetricEntryList()) { return(metricColl.GetMetricEntryList() == null); } if (null == metricColl.GetMetricEntryList()) { return(false); } // Else compare the entries bool fTagFound = false; uint cbLhs = this.MetricEntryCount; // No of entries in this block uint cbRhs = metricColl.MetricEntryCount; // No of entries in the block to be compared MetricEntry outside, inside; if (metricColl.MetricEntryCount <= MetricEntryCount) { outside = metricColl.GetMetricEntryList(); inside = GetMetricEntryList(); } else { inside = metricColl.GetMetricEntryList(); outside = GetMetricEntryList(); setType = SetType.SuperSet; } // For each entry in metricColl, search for the same in this Block. // If it is found, continue with the next entry of smaller Block. while (null != outside) { fTagFound = false; // Always start at the begining of the larger block MetricEntry temp = inside; while (null != temp) { if (outside.Compare(temp)) { fTagFound = true; break; } else { temp = temp.Next; } } if (!fTagFound) { return(false); } // Found the entry; Continue with the next entry in the outside block outside = outside.Next; } return(true); }