/// <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);
        }
Example #2
0
        /// <summary>
        /// Finds a guid based on Tag
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        public Guid FindGuid(KnownTagCache.KnownTagIndex tag)
        {
            if (tag < (KnownTagCache.KnownTagIndex)KnownIdCache.CustomGuidBaseIndex)
            {
                Guid guid = FindKnownGuid(tag);

                if (Guid.Empty != guid)
                {
                    return(guid);
                }

                return(FindCustomGuid(tag));
            }
            else
            {
                Guid guid = FindCustomGuid(tag);

                if (Guid.Empty != guid)
                {
                    return(guid);
                }

                return(FindKnownGuid(tag));
            }
        }
        /// <summary>
        /// Creates a metric entry based on a PropertyInfo and Tag and returns the Metric Entry Type created
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        public MetricEntryType CreateMetricEntry(StylusPointPropertyInfo propertyInfo, KnownTagCache.KnownTagIndex tag)
        {
            // First create the default Metric entry based on the property and type of metric entry and then use that to initialize the
            // metric entry data.
            uint index = 0;

            Tag = tag;

            MetricEntryType type;

            if (IsValidMetricEntry(propertyInfo, Tag, out type, out index))
            {
                switch (type)
                {
                case MetricEntryType.Optional:
                {
                    Initialize(propertyInfo, MetricEntry_Optional[index].PropertyMetrics);
                    break;
                }

                case MetricEntryType.Must:
                case MetricEntryType.Custom:
                    Initialize(propertyInfo, DefaultPropertyMetrics);
                    break;

                default:
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("MetricEntryType was persisted with Never flag which should never happen"));
                }
            }
            return(type);
        }
Example #4
0
        /// <summary>
        /// Finds a Custom Guid based on a Tag
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        Guid FindCustomGuid(KnownTagCache.KnownTagIndex tag)
        {
            if ((int)tag < (int)KnownIdCache.CustomGuidBaseIndex)
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Tag is outside of the known guid tag range"));
            }

            // Get the index in the OriginalISFIdTable array first
            int nIndex = (int)(tag - KnownIdCache.CustomGuidBaseIndex);

            // If invalid, return Guid.Empty
            if ((0 > nIndex) || (_CustomGuids.Count <= nIndex))
            {
                return(Guid.Empty);
            }

            // Otherwise, return the guid
            return((Guid)_CustomGuids[(int)nIndex]);
        }
Example #5
0
        /// <summary>
        /// Finds a known guid based on a Tag
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        static Guid FindKnownGuid(KnownTagCache.KnownTagIndex tag)
        {
            if (tag < KnownIdCache.KnownGuidBaseIndex)
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Tag is outside of the known guid tag range"));
            }

            // Get the index in the OriginalISFIdTable array first
            uint nIndex = (uint)(tag - KnownIdCache.KnownGuidBaseIndex);

            // If invalid, return Guid.Empty
            if (KnownIdCache.OriginalISFIdTable.Length <= nIndex)
            {
                return(Guid.Empty);
            }

            // Otherwise, return the guid
            return(KnownIdCache.OriginalISFIdTable[nIndex]);
        }
Example #6
0
        /// <summary>
        /// Finds a tag corresponding to a guids
        /// </summary>
        /// <param name="guid"></param>
        /// <param name="bFindInKnownListFirst"></param>
        /// <returns></returns>
        public KnownTagCache.KnownTagIndex FindTag(Guid guid, bool bFindInKnownListFirst)
        {
            KnownTagCache.KnownTagIndex tag = KnownTagCache.KnownTagIndex.Unknown;

            if (bFindInKnownListFirst)
            {
                tag = FindKnownTag(guid);
                if (KnownTagCache.KnownTagIndex.Unknown == tag)
                {
                    tag = FindCustomTag(guid);
                }
            }
            else
            {
                tag = FindCustomTag(guid);
                if (KnownTagCache.KnownTagIndex.Unknown == tag)
                {
                    tag = FindKnownTag(guid);
                }
            }

            return(tag);
        }
Example #7
0
        /// <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);
                }
            }
        }
Example #8
0
        /// <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);
        }
Example #9
0
 public MetricEntryList (KnownTagCache.KnownTagIndex tag, StylusPointPropertyInfo prop)
 {
     Tag = tag;
     PropertyMetrics = prop;
 }
Example #10
0
        /// <summary>
        /// Loads a single ExtendedProperty from the stream and add that to the list. Tag may be passed as in
        /// the case of Stroke ExtendedPropertyCollection where tag is stored in the stroke descriptor or 0 when tag
        /// is embeded in the stream
        /// </summary>
        /// <param name="stream">Memory buffer to load from</param>
        /// <param name="cbSize">Maximum length of buffer to read</param>
        /// <param name="guidList">Guid cache to read from</param>
        /// <param name="tag">Guid tag to lookup</param>
        /// <param name="guid">Guid of property</param>
        /// <param name="data">Data of property</param>
        /// <returns>Length of buffer read</returns>
#endif
        internal static uint DecodeAsISF(Stream stream, uint cbSize, GuidList guidList, KnownTagCache.KnownTagIndex tag, ref Guid guid, out object data)
        {
            uint cb, cbRead = 0;
            uint cbTotal = cbSize;

            if (0 == cbSize)
            {
                throw new InvalidOperationException(SR.Get(SRID.EmptyDataToLoad));
            }

            if (0 == tag) // no tag is passed, it must be embedded in the data
            {
                uint uiTag;
                cb  = SerializationHelper.Decode(stream, out uiTag);
                tag = (KnownTagCache.KnownTagIndex)uiTag;
                if (cb > cbTotal)
                {
                    throw new ArgumentException(SR.Get(SRID.InvalidSizeSpecified), "cbSize");
                }

                cbTotal -= cb;
                cbRead  += cb;
                System.Diagnostics.Debug.Assert(guid == Guid.Empty);
                guid = guidList.FindGuid(tag);
            }

            if (guid == Guid.Empty)
            {
                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Custom Attribute tag embedded in ISF stream does not match guid table"), "tag");
            }

            // Try and find the size
            uint size = GuidList.GetDataSizeIfKnownGuid(guid);

            if (size > cbTotal)
            {
                throw new ArgumentException(SR.Get(SRID.InvalidSizeSpecified), "cbSize");
            }

            // if the size is 0
            if (0 == size)
            {
                // Size must be embedded in the stream. Find out the compressed data size
                cb = SerializationHelper.Decode(stream, out size);

                uint cbInsize = size + 1;

                cbRead  += cb;
                cbTotal -= cb;
                if (cbInsize > cbTotal)
                {
                    throw new ArgumentException();
                }

                byte[] bytes = new byte[cbInsize];

                uint bytesRead = (uint)stream.Read(bytes, 0, (int)cbInsize);
                if (cbInsize != bytesRead)
                {
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Read different size from stream then expected"), "cbSize");
                }

                cbRead  += cbInsize;
                cbTotal -= cbInsize;

                //Find out the Decompressed buffer size
                using (MemoryStream decompressedStream = new MemoryStream(Compressor.DecompressPropertyData(bytes)))
                {
                    // Add the property
                    data = ExtendedPropertySerializer.DecodeAttribute(guid, decompressedStream);
                }
            }
            else
            {
                // For known size data, we just read the data directly from the stream
                byte[] bytes = new byte[size];

                uint bytesRead = (uint)stream.Read(bytes, 0, (int)size);
                if (size != bytesRead)
                {
                    throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Read different size from stream then expected"), "cbSize");
                }

                using (MemoryStream subStream = new MemoryStream(bytes))
                {
                    data = ExtendedPropertySerializer.DecodeAttribute(guid, subStream);
                }

                cbTotal -= size;
                cbRead  += size;
            }

            return(cbRead);
        }
        /// <summary>
        /// This function checks if this packet property results in a valid metric entry. This will be a valid entry if
        /// 1. it is a custom property, 2. Does not belong to the global list of gaMetricEntry_Never, 3. Belongs to the
        /// global list of gaMetricEntry_Must and 4. Belongs to global list of gaMetricEntry_Optional and at least one of
        /// its metric values is different from the corresponding default.
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <param name="tag"></param>
        /// <param name="metricEntryType"></param>
        /// <param name="index"></param>
        /// <returns></returns>

        static bool IsValidMetricEntry(StylusPointPropertyInfo propertyInfo, KnownTagCache.KnownTagIndex tag, out MetricEntryType metricEntryType, out uint index)
        {
            index = 0;
            // If this is a custom property, check if all the Metric values are null or not. If they are then this is not a
            // valid metric entry
            if (tag >= (KnownTagCache.KnownTagIndex)KnownIdCache.CustomGuidBaseIndex)
            {
                metricEntryType = MetricEntryType.Custom;
                if (Int32.MinValue == propertyInfo.Minimum &&
                    Int32.MaxValue == propertyInfo.Maximum &&
                    StylusPointPropertyUnit.None == propertyInfo.Unit &&
                    DoubleUtil.AreClose(1.0, propertyInfo.Resolution))
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                int ul;
                // First find the property in the gaMetricEntry_Never. If it belongs to this list,
                // we will never write the metric table for this prop. So return FALSE;
                for (ul = 0; ul < MetricEntry_Never.Length; ul++)
                {
                    if (MetricEntry_Never[ul] == tag)
                    {
                        metricEntryType = MetricEntryType.Never;
                        return(false);
                    }
                }

                // Then search the property in the gaMetricEntry_Must list. If it belongs to this list,
                // we must always write the metric table for this prop. So return TRUE;
                for (ul = 0; ul < MetricEntry_Must.Length; ul++)
                {
                    if (MetricEntry_Must[ul] == tag)
                    {
                        metricEntryType = MetricEntryType.Must;
                        if (propertyInfo.Minimum == DefaultPropertyMetrics.Minimum &&
                            propertyInfo.Maximum == DefaultPropertyMetrics.Maximum &&
                            propertyInfo.Unit == DefaultPropertyMetrics.Unit &&
                            DoubleUtil.AreClose(propertyInfo.Resolution, DefaultPropertyMetrics.Resolution))
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                }

                // Now seach it in the gaMetricEntry_Optional list. If it is there, check the metric values
                // agianst the default values and if there is any non default value, return TRUE;
                for (ul = 0; ul < MetricEntry_Optional.Length; ul++)
                {
                    if (((MetricEntryList)MetricEntry_Optional[ul]).Tag == tag)
                    {
                        metricEntryType = MetricEntryType.Optional;
                        if (propertyInfo.Minimum == MetricEntry_Optional[ul].PropertyMetrics.Minimum &&
                            propertyInfo.Maximum == MetricEntry_Optional[ul].PropertyMetrics.Maximum &&
                            propertyInfo.Unit == MetricEntry_Optional[ul].PropertyMetrics.Unit &&
                            DoubleUtil.AreClose(propertyInfo.Resolution, MetricEntry_Optional[ul].PropertyMetrics.Resolution))
                        {
                            return(false);
                        }
                        else
                        {
                            index = (uint)ul;
                            return(true);
                        }
                    }
                }
                // it is not found in any of the list. Force to write all metric entries for the property.
                metricEntryType = MetricEntryType.Must;
                return(true);
            }
        }
 public MetricEntryList(KnownTagCache.KnownTagIndex tag, StylusPointPropertyInfo prop)
 {
     Tag             = tag;
     PropertyMetrics = prop;
 }