/// <summary>
        /// Returns a new StylusPointDescription with the common StylusPointProperties from both
        /// </summary>
        /// <param name="stylusPointDescription">stylusPointDescription</param>
        /// <param name="stylusPointDescriptionPreserveInfo">stylusPointDescriptionPreserveInfo</param>
        /// <remarks>The StylusPointProperties from stylusPointDescriptionPreserveInfo will be returned in the new StylusPointDescription</remarks>
        public static StylusPointDescription GetCommonDescription(StylusPointDescription stylusPointDescription, StylusPointDescription stylusPointDescriptionPreserveInfo)
        {
            if (stylusPointDescription == null)
            {
                throw new ArgumentNullException("stylusPointDescription");
            }
            if (stylusPointDescriptionPreserveInfo == null)
            {
                throw new ArgumentNullException("stylusPointDescriptionPreserveInfo");
            }


            #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null.
            //
            // ignore X, Y, Pressure - they are guaranteed to be the first3 members
            //
            Debug.Assert(stylusPointDescription._stylusPointPropertyInfos.Length >= 3 &&
                         stylusPointDescription._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X &&
                         stylusPointDescription._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y &&
                         stylusPointDescription._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure);

            Debug.Assert(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length >= 3 &&
                         stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X &&
                         stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y &&
                         stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure);


            //add x, y, p
            List <StylusPointPropertyInfo> commonProperties = new List <StylusPointPropertyInfo>();
            commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[0]);
            commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[1]);
            commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[2]);

            //add common properties
            for (int x = RequiredCountOfProperties; x < stylusPointDescription._stylusPointPropertyInfos.Length; x++)
            {
                for (int y = RequiredCountOfProperties; y < stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos.Length; y++)
                {
                    if (StylusPointPropertyInfo.AreCompatible(stylusPointDescription._stylusPointPropertyInfos[x],
                                                              stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y]))
                    {
                        commonProperties.Add(stylusPointDescriptionPreserveInfo._stylusPointPropertyInfos[y]);
                    }
                }
            }
            #pragma warning restore 6506

            return(new StylusPointDescription(commonProperties));
        }
        /// <summary>
        /// Returns true if the two StylusPointDescriptions have the same StylusPointProperties.  Metrics are ignored.
        /// </summary>
        /// <param name="stylusPointDescription1">stylusPointDescription1</param>
        /// <param name="stylusPointDescription2">stylusPointDescription2</param>
        public static bool AreCompatible(StylusPointDescription stylusPointDescription1, StylusPointDescription stylusPointDescription2)
        {
            if (stylusPointDescription1 == null || stylusPointDescription2 == null)
            {
                throw new ArgumentNullException("stylusPointDescription");
            }

            #pragma warning disable 6506 // if a StylusPointDescription is not null, then _stylusPointPropertyInfos is not null.
            //
            // ignore X, Y, Pressure - they are guaranteed to be the first3 members
            //
            Debug.Assert(stylusPointDescription1._stylusPointPropertyInfos.Length >= RequiredCountOfProperties &&
                         stylusPointDescription1._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X &&
                         stylusPointDescription1._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y &&
                         stylusPointDescription1._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure);

            Debug.Assert(stylusPointDescription2._stylusPointPropertyInfos.Length >= RequiredCountOfProperties &&
                         stylusPointDescription2._stylusPointPropertyInfos[0].Id == StylusPointPropertyIds.X &&
                         stylusPointDescription2._stylusPointPropertyInfos[1].Id == StylusPointPropertyIds.Y &&
                         stylusPointDescription2._stylusPointPropertyInfos[2].Id == StylusPointPropertyIds.NormalPressure);

            if (stylusPointDescription1._stylusPointPropertyInfos.Length != stylusPointDescription2._stylusPointPropertyInfos.Length)
            {
                return(false);
            }
            for (int x = RequiredCountOfProperties; x < stylusPointDescription1._stylusPointPropertyInfos.Length; x++)
            {
                if (!StylusPointPropertyInfo.AreCompatible(stylusPointDescription1._stylusPointPropertyInfos[x], stylusPointDescription2._stylusPointPropertyInfos[x]))
                {
                    return(false);
                }
            }
            #pragma warning restore 6506

            return(true);
        }
        /// <summary>
        /// ToISFReadyArrays - Returns an array of arrays of packet values:
        ///
        /// int[]
        ///     - int[x,x,x,x,x,x]
        ///     - int[y,y,y,y,y,y]
        ///     - int[p,p,p,p,p,p]
        ///
        /// For ISF serialization
        ///
        /// Also returns if any non-default pressures were found or the metric for
        /// pressure was non-default
        ///
        /// </summary>
        internal void ToISFReadyArrays(out int[][] output, out bool shouldPersistPressure)
        {
            Debug.Assert(this.Count != 0, "Why are we serializing an empty StylusPointCollection???");
            //
            // X and Y are in Avalon units, we need to convert to HIMETRIC
            //

            //
            //


            int lengthPerPoint = this.Description.GetOutputArrayLengthPerPoint();

            if (this.Description.ButtonCount > 0)
            {
                //don't serialize button data. See Windows OS Bugs 1413460 for details
                lengthPerPoint--;
            }

            output = new int[lengthPerPoint][];
            for (int x = 0; x < lengthPerPoint; x++)
            {
                output[x] = new int[this.Count];
            }

            //
            // we serialize pressure if
            // 1) The StylusPointPropertyInfo for pressure is not the default
            // 2) There is at least one non-default pressure value in this SPC
            //
            StylusPointPropertyInfo pressureInfo =
                this.Description.GetPropertyInfo(StylusPointPropertyIds.NormalPressure);

            shouldPersistPressure =
                !StylusPointPropertyInfo.AreCompatible(pressureInfo, StylusPointPropertyInfoDefaults.NormalPressure);

            for (int b = 0; b < this.Count; b++)
            {
                StylusPoint stylusPoint = this[b];
                output[0][b] = (int)Math.Round(stylusPoint.X * StrokeCollectionSerializer.AvalonToHimetricMultiplier);
                output[1][b] = (int)Math.Round(stylusPoint.Y * StrokeCollectionSerializer.AvalonToHimetricMultiplier);
                output[2][b] = stylusPoint.GetPropertyValue(StylusPointProperties.NormalPressure);
                //
                // it's not necessary to check HasDefaultPressure if
                // allDefaultPressures is already set
                //
                if (!shouldPersistPressure && !stylusPoint.HasDefaultPressure)
                {
                    shouldPersistPressure = true;
                }
                if (lengthPerPoint > StylusPointDescription.RequiredCountOfProperties)
                {
                    int[] additionalData = stylusPoint.GetAdditionalData();
                    int   countToCopy    = lengthPerPoint - StylusPointDescription.RequiredCountOfProperties;/*3*/
                    Debug.Assert(this.Description.ButtonCount > 0 ?
                                 additionalData.Length - 1 == countToCopy :
                                 additionalData.Length == countToCopy);

                    for (int y = 0; y < countToCopy; y++)
                    {
                        output[y + 3][b] = additionalData[y];
                    }
                }
            }
        }