// Writes a collection of attributes representing properties with local values set on them.
        // If the value cannot be serialized as a string, adds the property to a collection of complexProperties.
        private static void WriteLocallySetProperties(Type elementTypeStandardized, ITextPointer context, XmlWriter xmlWriter, DependencyObject complexProperties)
        {
            TextPointer textPointer = context as TextPointer;
            if (textPointer == null)
            {
                // We can't have custom properties if we're not a TextPointer
                return;
            }

            LocalValueEnumerator locallySetProperties = context.GetLocalValueEnumerator();
            DependencyProperty[] inheritableProperties = TextSchema.GetInheritableProperties(elementTypeStandardized);
            DependencyProperty[] nonInheritableProperties = TextSchema.GetNoninheritableProperties(elementTypeStandardized);

            while (locallySetProperties.MoveNext())
            {
                DependencyProperty locallySetProperty = (DependencyProperty)locallySetProperties.Current.Property;
                
                // Don't serialize read-only properties, or any properties registered or owned by a
                // a class in the framework (we only want to serialize custom properties), to be
                // consistent with our behavior for non-custom inlines.
                // 
                if (!locallySetProperty.ReadOnly &&
                    !IsPropertyKnown(locallySetProperty, inheritableProperties, nonInheritableProperties) &&
                    !TextSchema.IsKnownType(locallySetProperty.OwnerType))
                {
                    object propertyValue = context.ReadLocalValue(locallySetProperty);
                    string stringValue = DPTypeDescriptorContext.GetStringValue(locallySetProperty, propertyValue);

                    if (stringValue != null)
                    {
                        stringValue = FilterNaNStringValueForDoublePropertyType(stringValue, locallySetProperty.PropertyType);

                        string propertyName = GetPropertyNameForElement(locallySetProperty, elementTypeStandardized, /*forceComplexName:*/false);
                        xmlWriter.WriteAttributeString(propertyName, stringValue);
                    }
                    else
                    {
                        complexProperties.SetValue(locallySetProperty, propertyValue);
                    }
                }
            }

// *** WE NEED TO BETTER UNDERSTAND THE IMPLICATIONS OF SERIALIZING NON-DP CLR PROPERTIES, SO THE REST OF
// *** THIS METHOD IS DISABLED UNTIL WE DECIDE THE BEST WAY TO HANDLE THEM.
// *** CLRTypeDescriptorContext is essentially the same as DPTypeDescriptorContext.
#if false
            // Check all CLR properties
            // Note that this is partially redundant.  TypeDescriptor.GetProperties, when called on a
            // DependencyObject, will return all properties that are set-- including all those already
            // serialized as Inheritable, NonInheritable, or LocallySet properties.  A potential
            // optimization, therefore, is to remove those serialization methods and simply use this one
            // for everything when we've opted into custom element serialization.
            PropertyDescriptorCollection descriptorCollection = TypeDescriptor.GetProperties(textPointer.Parent);
            IEnumerator descriptors = descriptorCollection.GetEnumerator();
            while (descriptors.MoveNext())
            {
                PropertyDescriptor current = (PropertyDescriptor)descriptors.Current;
                // ShouldSerializeValue() will return true for readonly properties that have explicitly
                // been told to serialize, such as Span.Inlines.  If we serialize a read-only property,
                // however, the parser will throw an exception when we try to deserialize.  So we
                // explicitly skip all read-only properties, and all DPs.
                if (!current.ShouldSerializeValue(textPointer.Parent) || current.IsReadOnly || current is MS.Internal.ComponentModel.DependencyObjectPropertyDescriptor)
                {
                    continue;
                }
                // Serialize the property
                object propertyValue = current.GetValue(textPointer.Parent);
                if (propertyValue != null)
                {
                    string stringValue = CLRTypeDescriptorContext.GetStringValue(current, propertyValue);

                    if (stringValue != null)
                    {
                        stringValue = FilterNaNStringValueForDoublePropertyType(stringValue, current.PropertyType);

                        xmlWriter.WriteAttributeString(current.Name, stringValue);
                    }
                    else
                    {
                        // 
                    }
                }
            }
#endif
        }
        // Writes a collection of attributes representing non-inheritable properties
        // whose values are set inline on the given element instance.
        // When we read properties fromContext we want all values including defaults; from text elements we only want only affected
        private static void WriteNoninheritableProperties(Type elementTypeStandardized, ITextPointer context, XmlWriter xmlWriter, bool onlyAffected, DependencyObject complexProperties)
        {
            DependencyProperty[] elementProperties = TextSchema.GetNoninheritableProperties(elementTypeStandardized);

            // We'll need a pointer to walk the tree up when onlyAffected=false
            ITextPointer parentContext = onlyAffected ? null : context.CreatePointer();

            for (int i = 0; i < elementProperties.Length; i++)
            {
                DependencyProperty property = elementProperties[i];
                Type propertyOwnerType = context.ParentType;

                object propertyValue;
                if (onlyAffected)
                {
                    // 

                    propertyValue = context.GetValue(property);
                }
                else
                {
                    // This is request for contextual properties - use "manual" inheritance to collect values
                    Invariant.Assert(elementTypeStandardized == typeof(Span), "Request for contextual properties is expected for Span wrapper only");

                    // Get property value from this element or from one of its ancestors (the latter in case of !onlyAffeted)
                    propertyValue = context.GetValue(property);

                    // Get property value from its ancestors if the property is not set. 
                    // TextDecorationCollection is special-cased as its default is empty collection, 
                    // and its value source cannot be distinguished from ITextPointer. 
                    if (propertyValue == null || TextDecorationCollection.Empty.ValueEquals(propertyValue as TextDecorationCollection))
                    {
                        if (property == Inline.BaselineAlignmentProperty || property == TextElement.TextEffectsProperty)
                        {
                            // These properties do not make sense as contextual; do not include them into context.
                            continue;
                        }

                        parentContext.MoveToPosition(context);
                        while ((propertyValue == null || TextDecorationCollection.Empty.ValueEquals(propertyValue as TextDecorationCollection))
                            && typeof(Inline).IsAssignableFrom(parentContext.ParentType))
                        {
                            parentContext.MoveToElementEdge(ElementEdge.BeforeStart);
                            propertyValue = parentContext.GetValue(property);
                            propertyOwnerType = parentContext.ParentType;
                        }
                    }
                }

                // 








                if ((property == Block.MarginProperty && (typeof(Paragraph).IsAssignableFrom(propertyOwnerType) || typeof(List).IsAssignableFrom(propertyOwnerType)))
                    ||
                    (property == Block.PaddingProperty) && typeof(List).IsAssignableFrom(propertyOwnerType))
                {
                    Thickness thickness = (Thickness)propertyValue;
                    if (Paragraph.IsMarginAuto(thickness))
                    {
                        continue;
                    }
                }

                // Write the property as attribute string or add it to a list of complex properties.
                WriteNoninheritableProperty(xmlWriter, property, propertyValue, propertyOwnerType, onlyAffected, complexProperties, context.ReadLocalValue(property));
            }
        }