/*
 * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc.
 * Copyright (C) 2010, 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "EditingStyle.h"

#include "ApplyStyleCommand.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSFontFamily.h"
#include "CSSFontStyleValue.h"
#include "CSSParser.h"
#include "CSSRuleList.h"
#include "CSSStyleRule.h"
#include "CSSValueList.h"
#include "CSSValuePool.h"
#include "ColorSerialization.h"
#include "Editing.h"
#include "Editor.h"
#include "ElementInlines.h"
#include "FontCache.h"
#include "FontCascade.h"
#include "Frame.h"
#include "HTMLFontElement.h"
#include "HTMLInterchange.h"
#include "HTMLNames.h"
#include "HTMLSpanElement.h"
#include "Node.h"
#include "NodeTraversal.h"
#include "QualifiedName.h"
#include "Range.h"
#include "RenderElement.h"
#include "RenderStyle.h"
#include "SimpleRange.h"
#include "StyleFontSizeFunctions.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
#include "StyleRule.h"
#include "StyledElement.h"
#include "VisibleUnits.h"

namespace WebCore {

// Editing style properties must be preserved during editing operation.
// e.g. when a user inserts a new paragraph, all properties listed here must be copied to the new paragraph.
static const CSSPropertyID editingProperties[] = {
    CSSPropertyCaretColor,
    CSSPropertyColor,
    CSSPropertyFontFamily,
    CSSPropertyFontSize,
    CSSPropertyFontStyle,
    CSSPropertyFontVariantCaps,
    CSSPropertyFontWeight,
    CSSPropertyLetterSpacing,
    CSSPropertyOrphans,
    CSSPropertyTextAlign,
    CSSPropertyTextIndent,
    CSSPropertyTextTransform,
    CSSPropertyWhiteSpace,
    CSSPropertyWidows,
    CSSPropertyWordSpacing,
#if ENABLE(TOUCH_EVENTS)
    CSSPropertyWebkitTapHighlightColor,
#endif
    CSSPropertyWebkitTextDecorationsInEffect,
    CSSPropertyWebkitTextFillColor,
#if ENABLE(TEXT_AUTOSIZING)
    CSSPropertyWebkitTextSizeAdjust,
#endif
    CSSPropertyWebkitTextStrokeColor,
    CSSPropertyWebkitTextStrokeWidth,

    // Non-inheritable properties
    CSSPropertyBackgroundColor,
    CSSPropertyTextDecoration,
};

const unsigned numAllEditingProperties = WTF_ARRAY_LENGTH(editingProperties);
const unsigned numInheritableEditingProperties = numAllEditingProperties - 2;

enum EditingPropertiesToInclude { OnlyInheritableEditingProperties, AllEditingProperties };
template <class StyleDeclarationType>
static Ref<MutableStyleProperties> copyEditingProperties(StyleDeclarationType* style, EditingPropertiesToInclude type)
{
    if (type == AllEditingProperties)
        return style->copyPropertiesInSet(editingProperties, numAllEditingProperties);
    return style->copyPropertiesInSet(editingProperties, numInheritableEditingProperties);
}

static inline bool isEditingProperty(int id)
{
    for (auto& editingProperty : editingProperties) {
        if (editingProperty == id)
            return true;
    }
    return false;
}

static Ref<MutableStyleProperties> copyPropertiesFromComputedStyle(ComputedStyleExtractor& computedStyle, EditingStyle::PropertiesToInclude propertiesToInclude)
{
    switch (propertiesToInclude) {
    case EditingStyle::OnlyEditingInheritableProperties:
        return copyEditingProperties(&computedStyle, OnlyInheritableEditingProperties);
    case EditingStyle::EditingPropertiesInEffect:
        return copyEditingProperties(&computedStyle, AllEditingProperties);
    case EditingStyle::AllProperties:
        break;
    }
    return computedStyle.copyProperties();
}

static Ref<MutableStyleProperties> copyPropertiesFromComputedStyle(Node* node, EditingStyle::PropertiesToInclude propertiesToInclude)
{
    ComputedStyleExtractor computedStyle(node);
    return copyPropertiesFromComputedStyle(computedStyle, propertiesToInclude);
}

static RefPtr<CSSValue> extractPropertyValue(const StyleProperties& style, CSSPropertyID propertyID)
{
    return style.getPropertyCSSValue(propertyID);
}

static RefPtr<CSSValue> extractPropertyValue(ComputedStyleExtractor& computedStyle, CSSPropertyID propertyID)
{
    return computedStyle.propertyValue(propertyID);
}

template<typename T>
int identifierForStyleProperty(T& style, CSSPropertyID propertyID)
{
    RefPtr<CSSValue> value = extractPropertyValue(style, propertyID);
    if (propertyID == CSSPropertyFontStyle && is<CSSFontStyleValue>(value) && downcast<CSSFontStyleValue>(value.get())->isItalicOrOblique())
        return CSSValueItalic;
    if (!is<CSSPrimitiveValue>(value))
        return 0;
    auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
    if (propertyID == CSSPropertyFontWeight && primitiveValue.isNumber() && primitiveValue.doubleValue(CSSUnitType::CSS_NUMBER) >= boldThreshold())
        return CSSValueBold;
    return primitiveValue.valueID();
}

template<typename T> Ref<MutableStyleProperties> getPropertiesNotIn(StyleProperties& styleWithRedundantProperties, T& baseStyle);
enum LegacyFontSizeMode { AlwaysUseLegacyFontSize, UseLegacyFontSizeOnlyIfPixelValuesMatch };
static int legacyFontSizeFromCSSValue(Document&, CSSPrimitiveValue*, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode);
static bool hasTransparentBackgroundColor(StyleProperties*);
static RefPtr<CSSValue> backgroundColorInEffect(Node*);

class HTMLElementEquivalent {
    WTF_MAKE_FAST_ALLOCATED;
public:
    HTMLElementEquivalent(CSSPropertyID, CSSValueID primitiveValue, const QualifiedName& tagName);
    virtual ~HTMLElementEquivalent() = default;

    virtual bool matches(const Element& element) const { return !m_tagName || element.hasTagName(*m_tagName); }
    virtual bool hasAttribute() const { return false; }
    virtual bool propertyExistsInStyle(const EditingStyle& style) const { return style.m_mutableStyle && style.m_mutableStyle->getPropertyCSSValue(m_propertyID); }
    virtual bool valueIsPresentInStyle(Element&, const EditingStyle&) const;
    virtual void addToStyle(Element*, EditingStyle*) const;

protected:
    HTMLElementEquivalent(CSSPropertyID);
    HTMLElementEquivalent(CSSPropertyID, const QualifiedName& tagName);
    const CSSPropertyID m_propertyID;
    const RefPtr<CSSPrimitiveValue> m_primitiveValue;
    const QualifiedName* m_tagName { nullptr }; // We can store a pointer because HTML tag names are const global.
};

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id)
    : m_propertyID(id)
{
}

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, const QualifiedName& tagName)
    : m_propertyID(id)
    , m_tagName(&tagName)
{
}

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id, CSSValueID primitiveValue, const QualifiedName& tagName)
    : m_propertyID(id)
    , m_primitiveValue(CSSPrimitiveValue::createIdentifier(primitiveValue))
    , m_tagName(&tagName)
{
    ASSERT(primitiveValue != CSSValueInvalid);
}

bool HTMLElementEquivalent::valueIsPresentInStyle(Element& element, const EditingStyle& style) const
{
    RefPtr<CSSValue> value = style.m_mutableStyle->getPropertyCSSValue(m_propertyID);
    return matches(element) && is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(*value).valueID() == m_primitiveValue->valueID();
}

void HTMLElementEquivalent::addToStyle(Element*, EditingStyle* style) const
{
    style->setProperty(m_propertyID, m_primitiveValue->cssText());
}

class HTMLTextDecorationEquivalent : public HTMLElementEquivalent {
public:
    HTMLTextDecorationEquivalent(CSSValueID primitiveValue, const QualifiedName& tagName)
        : HTMLElementEquivalent(CSSPropertyTextDecoration, primitiveValue, tagName)
        , m_isUnderline(primitiveValue == CSSValueUnderline)
    {
    }

    bool propertyExistsInStyle(const EditingStyle& style) const override
    {
        if (changeInStyle(style) != TextDecorationChange::None)
            return true;

        if (!style.m_mutableStyle)
            return false;

        auto& mutableStyle = *style.m_mutableStyle;
        return mutableStyle.getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect)
            || mutableStyle.getPropertyCSSValue(CSSPropertyTextDecoration);
    }

    bool valueIsPresentInStyle(Element& element, const EditingStyle& style) const override
    {
        if (!matches(element))
            return false;
        auto change = changeInStyle(style);
        if (change != TextDecorationChange::None)
            return change == TextDecorationChange::Add;
        RefPtr<CSSValue> styleValue = style.m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
        if (!styleValue)
            styleValue = style.m_mutableStyle->getPropertyCSSValue(CSSPropertyTextDecoration);
        return is<CSSValueList>(styleValue) && downcast<CSSValueList>(*styleValue).hasValue(m_primitiveValue.get());
    }

private:
    TextDecorationChange changeInStyle(const EditingStyle& style) const
    {
        return m_isUnderline ? style.underlineChange() : style.strikeThroughChange();
    }

    bool m_isUnderline;
};

static bool fontWeightIsBold(CSSValue& fontWeight)
{
    if (!is<CSSPrimitiveValue>(fontWeight))
        return false;

    auto& primitiveValue = downcast<CSSPrimitiveValue>(fontWeight);
    if (primitiveValue.isCSSWideKeyword())
        return false;

    switch (primitiveValue.valueID()) {
    case CSSValueNormal:
        return false;
    case CSSValueBold:
        return true;
    default:
        break;
    }

    ASSERT(primitiveValue.isNumber());
    return primitiveValue.floatValue() >= static_cast<float>(boldThreshold());
}

class HTMLFontWeightEquivalent : public HTMLElementEquivalent {
public:
    HTMLFontWeightEquivalent(const QualifiedName& tagName)
        : HTMLElementEquivalent(CSSPropertyFontWeight, CSSValueBold, tagName)
    {
    }

private:
    bool valueIsPresentInStyle(Element& element, const EditingStyle& style) const
    {
        RefPtr<CSSValue> value = style.m_mutableStyle->getPropertyCSSValue(m_propertyID);
        return matches(element) && value && fontWeightIsBold(*value);
    }
};

class HTMLAttributeEquivalent : public HTMLElementEquivalent {
public:
    HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& tagName, const QualifiedName& attrName);
    HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& attrName);

    bool matches(const Element& element) const override { return HTMLElementEquivalent::matches(element) && element.hasAttribute(m_attrName); }
    bool hasAttribute() const override { return true; }
    bool valueIsPresentInStyle(Element&, const EditingStyle&) const override;
    void addToStyle(Element*, EditingStyle*) const override;
    virtual RefPtr<CSSValue> attributeValueAsCSSValue(Element*) const;
    inline const QualifiedName& attributeName() const { return m_attrName; }

protected:
    const QualifiedName& m_attrName; // We can store a reference because HTML attribute names are const global.
};

HTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, const QualifiedName& tagName, const QualifiedName& attrName)
    : HTMLElementEquivalent(id, tagName)
    , m_attrName(attrName)
{
}

HTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id, const QualifiedName& attrName)
    : HTMLElementEquivalent(id)
    , m_attrName(attrName)
{
}

bool HTMLAttributeEquivalent::valueIsPresentInStyle(Element& element, const EditingStyle& style) const
{
    RefPtr<CSSValue> value = attributeValueAsCSSValue(&element);
    RefPtr<CSSValue> styleValue = style.m_mutableStyle->getPropertyCSSValue(m_propertyID);
    
    return compareCSSValuePtr(value, styleValue);
}

void HTMLAttributeEquivalent::addToStyle(Element* element, EditingStyle* style) const
{
    if (RefPtr<CSSValue> value = attributeValueAsCSSValue(element))
        style->setProperty(m_propertyID, value->cssText());
}

RefPtr<CSSValue> HTMLAttributeEquivalent::attributeValueAsCSSValue(Element* element) const
{
    ASSERT(element);
    const AtomString& value = element->getAttribute(m_attrName);
    if (value.isNull())
        return nullptr;
    
    RefPtr<MutableStyleProperties> dummyStyle;
    dummyStyle = MutableStyleProperties::create();
    dummyStyle->setProperty(m_propertyID, value);
    return dummyStyle->getPropertyCSSValue(m_propertyID);
}

class HTMLFontSizeEquivalent : public HTMLAttributeEquivalent {
public:
    HTMLFontSizeEquivalent();

    RefPtr<CSSValue> attributeValueAsCSSValue(Element*) const override;
};

HTMLFontSizeEquivalent::HTMLFontSizeEquivalent()
    : HTMLAttributeEquivalent(CSSPropertyFontSize, HTMLNames::fontTag, HTMLNames::sizeAttr)
{
}

RefPtr<CSSValue> HTMLFontSizeEquivalent::attributeValueAsCSSValue(Element* element) const
{
    ASSERT(element);
    const AtomString& value = element->getAttribute(m_attrName);
    if (value.isNull())
        return nullptr;
    CSSValueID size;
    if (!HTMLFontElement::cssValueFromFontSizeNumber(value, size))
        return nullptr;
    return CSSPrimitiveValue::createIdentifier(size);
}

float EditingStyle::NoFontDelta = 0.0f;

EditingStyle::EditingStyle()
    : m_shouldUseFixedDefaultFontSize(false)
    , m_underlineChange(static_cast<unsigned>(TextDecorationChange::None))
    , m_strikeThroughChange(static_cast<unsigned>(TextDecorationChange::None))
{
}

EditingStyle::EditingStyle(Node* node, PropertiesToInclude propertiesToInclude)
    : EditingStyle()
{
    init(node, propertiesToInclude);
}

EditingStyle::EditingStyle(const Position& position, PropertiesToInclude propertiesToInclude)
    : EditingStyle()
{
    init(position.deprecatedNode(), propertiesToInclude);
}

EditingStyle::EditingStyle(const CSSStyleDeclaration* style)
    : EditingStyle()
{
    if (style)
        m_mutableStyle = style->copyProperties();
    extractFontSizeDelta();
}

EditingStyle::EditingStyle(const StyleProperties* style)
    : EditingStyle()
{
    if (style)
        m_mutableStyle = style->mutableCopy();
    extractFontSizeDelta();
}

EditingStyle::EditingStyle(CSSPropertyID propertyID, const String& value)
    : EditingStyle()
{
    setProperty(propertyID, value);
    extractFontSizeDelta();
}

EditingStyle::EditingStyle(CSSPropertyID propertyID, CSSValueID value)
    : EditingStyle()
{
    m_mutableStyle = MutableStyleProperties::create();
    m_mutableStyle->setProperty(propertyID, value);
    extractFontSizeDelta();
}

EditingStyle::~EditingStyle() = default;

static Color cssValueToColor(CSSValue* colorValue)
{
    if (!is<CSSPrimitiveValue>(colorValue))
        return Color::transparentBlack;
    
    CSSPrimitiveValue& primitiveColor = downcast<CSSPrimitiveValue>(*colorValue);
    if (primitiveColor.isRGBColor())
        return primitiveColor.color();
    
    return CSSParser::parseColorWithoutContext(colorValue->cssText());
}

template<typename T>
static inline Color textColorFromStyle(T& style)
{
    return cssValueToColor(extractPropertyValue(style, CSSPropertyColor).get());
}

template<typename T>
static inline Color caretColorFromStyle(T& style)
{
    return cssValueToColor(extractPropertyValue(style, CSSPropertyCaretColor).get());
}

template<typename T>
static inline Color backgroundColorFromStyle(T& style)
{
    return cssValueToColor(extractPropertyValue(style, CSSPropertyBackgroundColor).get());
}

static inline Color rgbaBackgroundColorInEffect(Node* node)
{
    return cssValueToColor(backgroundColorInEffect(node).get());
}

static int textAlignResolvingStartAndEnd(int textAlign, int direction)
{
    switch (textAlign) {
    case CSSValueCenter:
    case CSSValueWebkitCenter:
        return CSSValueCenter;
    case CSSValueJustify:
        return CSSValueJustify;
    case CSSValueLeft:
    case CSSValueWebkitLeft:
        return CSSValueLeft;
    case CSSValueRight:
    case CSSValueWebkitRight:
        return CSSValueRight;
    case CSSValueStart:
        return direction != CSSValueRtl ? CSSValueLeft : CSSValueRight;
    case CSSValueEnd:
        return direction == CSSValueRtl ? CSSValueRight : CSSValueLeft;
    }
    return CSSValueInvalid;
}

template<typename T>
static int textAlignResolvingStartAndEnd(T& style)
{
    return textAlignResolvingStartAndEnd(identifierForStyleProperty(style, CSSPropertyTextAlign), identifierForStyleProperty(style, CSSPropertyDirection));
}

void EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude)
{
    if (isTabSpanTextNode(node))
        node = tabSpanNode(node)->parentNode();
    else if (isTabSpanNode(node))
        node = node->parentNode();

    ComputedStyleExtractor computedStyleAtPosition(node);
    // FIXME: It's strange to not set background-color and text-decoration when propertiesToInclude is EditingPropertiesInEffect.
    // However editing/selection/contains-boundaries.html fails without this ternary.
    m_mutableStyle = copyPropertiesFromComputedStyle(computedStyleAtPosition,
        propertiesToInclude == EditingPropertiesInEffect ? OnlyEditingInheritableProperties : propertiesToInclude);

    if (propertiesToInclude == EditingPropertiesInEffect) {
        if (RefPtr<CSSValue> value = backgroundColorInEffect(node))
            m_mutableStyle->setProperty(CSSPropertyBackgroundColor, value->cssText());
        if (RefPtr<CSSValue> value = computedStyleAtPosition.propertyValue(CSSPropertyWebkitTextDecorationsInEffect)) {
            m_mutableStyle->setProperty(CSSPropertyTextDecoration, value->cssText());
            m_mutableStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
        }
    }

    if (node && node->computedStyle()) {
        auto* renderStyle = node->computedStyle();
        removeTextFillAndStrokeColorsIfNeeded(renderStyle);
        if (renderStyle->fontDescription().keywordSize()) {
            if (auto cssValue = computedStyleAtPosition.getFontSizeCSSValuePreferringKeyword())
                m_mutableStyle->setProperty(CSSPropertyFontSize, cssValue->cssText());
        }
    }

    m_shouldUseFixedDefaultFontSize = computedStyleAtPosition.useFixedFontDefaultSize();
    extractFontSizeDelta();
}

void EditingStyle::removeTextFillAndStrokeColorsIfNeeded(const RenderStyle* renderStyle)
{
    // If a node's text fill color is invalid, then its children use 
    // their font-color as their text fill color (they don't
    // inherit it).  Likewise for stroke color.
    if (!renderStyle->textFillColor().isValid())
        m_mutableStyle->removeProperty(CSSPropertyWebkitTextFillColor);
    if (!renderStyle->textStrokeColor().isValid())
        m_mutableStyle->removeProperty(CSSPropertyWebkitTextStrokeColor);
}

void EditingStyle::setProperty(CSSPropertyID propertyID, const String& value, bool important)
{
    if (!m_mutableStyle)
        m_mutableStyle = MutableStyleProperties::create();

    m_mutableStyle->setProperty(propertyID, value, important);
}

void EditingStyle::extractFontSizeDelta()
{
    if (!m_mutableStyle)
        return;

    if (m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize)) {
        // Explicit font size overrides any delta.
        m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta);
        return;
    }

    // Get the adjustment amount out of the style.
    RefPtr<CSSValue> value = m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitFontSizeDelta);
    if (!is<CSSPrimitiveValue>(value))
        return;

    CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(*value);

    // Only PX handled now. If we handle more types in the future, perhaps
    // a switch statement here would be more appropriate.
    if (!primitiveValue.isPx())
        return;

    m_fontSizeDelta = primitiveValue.floatValue();
    m_mutableStyle->removeProperty(CSSPropertyWebkitFontSizeDelta);
}

bool EditingStyle::isEmpty() const
{
    return (!m_mutableStyle || m_mutableStyle->isEmpty()) && m_fontSizeDelta == NoFontDelta
        && underlineChange() == TextDecorationChange::None && strikeThroughChange() == TextDecorationChange::None;
}

Ref<MutableStyleProperties> EditingStyle::styleWithResolvedTextDecorations() const
{
    bool hasTextDecorationChanges = underlineChange() != TextDecorationChange::None || strikeThroughChange() != TextDecorationChange::None;
    if (m_mutableStyle && !hasTextDecorationChanges)
        return *m_mutableStyle;

    Ref<MutableStyleProperties> style = m_mutableStyle ? m_mutableStyle->mutableCopy() : MutableStyleProperties::create();

    Ref<CSSValueList> valueList = CSSValueList::createSpaceSeparated();
    if (underlineChange() == TextDecorationChange::Add)
        valueList->append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnderline));
    if (strikeThroughChange() == TextDecorationChange::Add)
        valueList->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLineThrough));

    if (valueList->length())
        style->setProperty(CSSPropertyTextDecoration, valueList.ptr());
    else
        style->setProperty(CSSPropertyTextDecoration, CSSValuePool::singleton().createIdentifierValue(CSSValueNone));

    return style;
}

std::optional<WritingDirection> EditingStyle::textDirection() const
{
    if (!m_mutableStyle)
        return std::nullopt;

    RefPtr<CSSValue> unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
    if (!is<CSSPrimitiveValue>(unicodeBidi))
        return std::nullopt;

    CSSValueID unicodeBidiValue = downcast<CSSPrimitiveValue>(*unicodeBidi).valueID();
    if (unicodeBidiValue == CSSValueEmbed) {
        RefPtr<CSSValue> direction = m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
        if (!is<CSSPrimitiveValue>(direction))
            return std::nullopt;

        return downcast<CSSPrimitiveValue>(*direction).valueID() == CSSValueLtr ? WritingDirection::LeftToRight : WritingDirection::RightToLeft;
    }

    if (unicodeBidiValue == CSSValueNormal)
        return WritingDirection::Natural;

    return std::nullopt;
}

void EditingStyle::setStyle(RefPtr<MutableStyleProperties>&& style)
{
    m_mutableStyle = WTFMove(style);
    // FIXME: We should be able to figure out whether or not font is fixed width for mutable style.
    // We need to check font-family is monospace as in FontDescription but we don't want to duplicate code here.
    m_shouldUseFixedDefaultFontSize = false;
    extractFontSizeDelta();
}

void EditingStyle::overrideWithStyle(const StyleProperties& style)
{
    return mergeStyle(&style, OverrideValues);
}

static void applyTextDecorationChangeToValueList(CSSValueList& valueList, TextDecorationChange change, Ref<CSSPrimitiveValue>&& value)
{
    switch (change) {
    case TextDecorationChange::None:
        break;
    case TextDecorationChange::Add:
        valueList.append(WTFMove(value));
        break;
    case TextDecorationChange::Remove:
        valueList.removeAll(&value.get());
        break;
    }
}

void EditingStyle::overrideTypingStyleAt(const EditingStyle& style, const Position& position)
{
    mergeStyle(style.m_mutableStyle.get(), OverrideValues);

    m_fontSizeDelta += style.m_fontSizeDelta;

    prepareToApplyAt(position, EditingStyle::PreserveWritingDirection);

    auto underlineChange = style.underlineChange();
    auto strikeThroughChange = style.strikeThroughChange();
    if (underlineChange == TextDecorationChange::None && strikeThroughChange == TextDecorationChange::None)
        return;

    if (!m_mutableStyle)
        m_mutableStyle = MutableStyleProperties::create();

    auto& cssValuePool = CSSValuePool::singleton();
    Ref<CSSPrimitiveValue> underline = cssValuePool.createIdentifierValue(CSSValueUnderline);
    Ref<CSSPrimitiveValue> lineThrough = cssValuePool.createIdentifierValue(CSSValueLineThrough);
    RefPtr<CSSValue> value = m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
    RefPtr<CSSValueList> valueList;
    if (value && value->isValueList()) {
        valueList = downcast<CSSValueList>(*value).copy();
        applyTextDecorationChangeToValueList(*valueList, underlineChange, WTFMove(underline));
        applyTextDecorationChangeToValueList(*valueList, strikeThroughChange, WTFMove(lineThrough));
    } else {
        valueList = CSSValueList::createSpaceSeparated();
        if (underlineChange == TextDecorationChange::Add)
            valueList->append(WTFMove(underline));
        if (strikeThroughChange == TextDecorationChange::Add)
            valueList->append(WTFMove(lineThrough));
    }
    m_mutableStyle->setProperty(CSSPropertyWebkitTextDecorationsInEffect, valueList.get());
}

void EditingStyle::clear()
{
    m_mutableStyle = nullptr;
    m_shouldUseFixedDefaultFontSize = false;
    m_fontSizeDelta = NoFontDelta;
    setUnderlineChange(TextDecorationChange::None);
    setStrikeThroughChange(TextDecorationChange::None);
}

Ref<EditingStyle> EditingStyle::copy() const
{
    auto copy = EditingStyle::create();
    if (m_mutableStyle)
        copy->m_mutableStyle = m_mutableStyle->mutableCopy();
    copy->m_shouldUseFixedDefaultFontSize = m_shouldUseFixedDefaultFontSize;
    copy->m_underlineChange = m_underlineChange;
    copy->m_strikeThroughChange = m_strikeThroughChange;
    copy->m_fontSizeDelta = m_fontSizeDelta;
    return copy;
}

Ref<EditingStyle> EditingStyle::extractAndRemoveBlockProperties()
{
    auto blockProperties = EditingStyle::create();
    if (!m_mutableStyle)
        return blockProperties;

    blockProperties->m_mutableStyle = m_mutableStyle->copyBlockProperties();
    m_mutableStyle->removeBlockProperties();

    return blockProperties;
}

Ref<EditingStyle> EditingStyle::extractAndRemoveTextDirection()
{
    auto textDirection = EditingStyle::create();
    textDirection->m_mutableStyle = MutableStyleProperties::create();
    textDirection->m_mutableStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed, m_mutableStyle->propertyIsImportant(CSSPropertyUnicodeBidi));
    textDirection->m_mutableStyle->setProperty(CSSPropertyDirection, m_mutableStyle->getPropertyValue(CSSPropertyDirection),
        m_mutableStyle->propertyIsImportant(CSSPropertyDirection));

    m_mutableStyle->removeProperty(CSSPropertyUnicodeBidi);
    m_mutableStyle->removeProperty(CSSPropertyDirection);

    return textDirection;
}

void EditingStyle::removeBlockProperties()
{
    if (!m_mutableStyle)
        return;

    m_mutableStyle->removeBlockProperties();
}

void EditingStyle::removeStyleAddedByNode(Node* node)
{
    if (!node || !node->parentNode())
        return;
    RefPtr<MutableStyleProperties> parentStyle = copyPropertiesFromComputedStyle(node->parentNode(), EditingPropertiesInEffect);
    RefPtr<MutableStyleProperties> nodeStyle = copyPropertiesFromComputedStyle(node, EditingPropertiesInEffect);
    removeEquivalentProperties(*parentStyle);
    removeEquivalentProperties(*nodeStyle);
}

void EditingStyle::removeStyleConflictingWithStyleOfNode(Node& node)
{
    if (!node.parentNode() || !m_mutableStyle)
        return;

    RefPtr<MutableStyleProperties> parentStyle = copyPropertiesFromComputedStyle(node.parentNode(), EditingPropertiesInEffect);
    auto nodeStyle = EditingStyle::create(&node, EditingPropertiesInEffect);
    nodeStyle->removeEquivalentProperties(*parentStyle);

    MutableStyleProperties* style = nodeStyle->style();
    unsigned propertyCount = style->propertyCount();
    for (unsigned i = 0; i < propertyCount; ++i)
        m_mutableStyle->removeProperty(style->propertyAt(i).id());
}

void EditingStyle::collapseTextDecorationProperties()
{
    if (!m_mutableStyle)
        return;

    RefPtr<CSSValue> textDecorationsInEffect = m_mutableStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
    if (!textDecorationsInEffect)
        return;

    if (textDecorationsInEffect->isValueList())
        m_mutableStyle->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText(), m_mutableStyle->propertyIsImportant(CSSPropertyTextDecoration));
    else
        m_mutableStyle->removeProperty(CSSPropertyTextDecoration);
    m_mutableStyle->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
}

// CSS properties that create a visual difference only when applied to text.
static const CSSPropertyID textOnlyProperties[] = {
    CSSPropertyTextDecoration,
    CSSPropertyWebkitTextDecorationsInEffect,
    CSSPropertyFontStyle,
    CSSPropertyFontWeight,
    CSSPropertyColor,
};

TriState EditingStyle::triStateOfStyle(EditingStyle* style) const
{
    if (!style || !style->m_mutableStyle)
        return TriState::False;
    return triStateOfStyle(*style->m_mutableStyle, DoNotIgnoreTextOnlyProperties);
}

template<typename T>
TriState EditingStyle::triStateOfStyle(T& styleToCompare, ShouldIgnoreTextOnlyProperties shouldIgnoreTextOnlyProperties) const
{
    if (!m_mutableStyle)
        return TriState::True;

    RefPtr<MutableStyleProperties> difference = getPropertiesNotIn(*m_mutableStyle, styleToCompare);

    if (shouldIgnoreTextOnlyProperties == IgnoreTextOnlyProperties)
        difference->removePropertiesInSet(textOnlyProperties, WTF_ARRAY_LENGTH(textOnlyProperties));

    if (difference->isEmpty())
        return TriState::True;
    if (difference->propertyCount() == m_mutableStyle->propertyCount())
        return TriState::False;

    return TriState::Indeterminate;
}

TriState EditingStyle::triStateOfStyle(const VisibleSelection& selection) const
{
    if (!selection.isCaretOrRange())
        return TriState::False;

    if (selection.isCaret())
        return triStateOfStyle(EditingStyle::styleAtSelectionStart(selection).get());

    TriState state = TriState::False;
    bool nodeIsStart = true;
    for (Node* node = selection.start().deprecatedNode(); node; node = NodeTraversal::next(*node)) {
        if (node->renderer() && node->hasEditableStyle()) {
            ComputedStyleExtractor computedStyle(node);
            TriState nodeState = triStateOfStyle(computedStyle, node->isTextNode() ? EditingStyle::DoNotIgnoreTextOnlyProperties : EditingStyle::IgnoreTextOnlyProperties);
            if (nodeIsStart) {
                state = nodeState;
                nodeIsStart = false;
            } else if (state != nodeState && node->isTextNode()) {
                state = TriState::Indeterminate;
                break;
            }
        }

        if (node == selection.end().deprecatedNode())
            break;
    }

    return state;
}

static RefPtr<CSSValueList> textDecorationValueList(const StyleProperties& properties)
{
    RefPtr<CSSValue> value = properties.getPropertyCSSValue(CSSPropertyTextDecoration);
    if (!is<CSSValueList>(value))
        return nullptr;
    return downcast<CSSValueList>(value.get());
}

bool EditingStyle::conflictsWithInlineStyleOfElement(StyledElement& element, RefPtr<MutableStyleProperties>* newInlineStylePtr, EditingStyle* extractedStyle) const
{
    const StyleProperties* inlineStyle = element.inlineStyle();
    if (!inlineStyle)
        return false;
    bool conflicts = false;
    RefPtr<MutableStyleProperties> newInlineStyle;
    if (newInlineStylePtr) {
        newInlineStyle = inlineStyle->mutableCopy();
        *newInlineStylePtr = newInlineStyle;
    }

    bool shouldRemoveUnderline = underlineChange() == TextDecorationChange::Remove;
    bool shouldRemoveStrikeThrough = strikeThroughChange() == TextDecorationChange::Remove;
    if (shouldRemoveUnderline || shouldRemoveStrikeThrough) {
        if (RefPtr<CSSValueList> valueList = textDecorationValueList(*inlineStyle)) {
            auto newValueList = valueList->copy();
            auto extractedValueList = CSSValueList::createSpaceSeparated();

            Ref<CSSPrimitiveValue> underline = CSSValuePool::singleton().createIdentifierValue(CSSValueUnderline);
            if (shouldRemoveUnderline && valueList->hasValue(underline.ptr())) {
                if (!newInlineStyle)
                    return true;
                newValueList->removeAll(underline.ptr());
                extractedValueList->append(WTFMove(underline));
            }

            Ref<CSSPrimitiveValue> lineThrough = CSSValuePool::singleton().createIdentifierValue(CSSValueLineThrough);
            if (shouldRemoveStrikeThrough && valueList->hasValue(lineThrough.ptr())) {
                if (!newInlineStyle)
                    return true;
                newValueList->removeAll(lineThrough.ptr());
                extractedValueList->append(WTFMove(lineThrough));
            }

            if (extractedValueList->length()) {
                conflicts = true;
                if (newValueList->length())
                    newInlineStyle->setProperty(CSSPropertyTextDecoration, WTFMove(newValueList));
                else
                    newInlineStyle->removeProperty(CSSPropertyTextDecoration);

                if (extractedStyle) {
                    bool isImportant = inlineStyle->propertyIsImportant(CSSPropertyTextDecoration);
                    extractedStyle->setProperty(CSSPropertyTextDecoration, extractedValueList->cssText(), isImportant);
                }
            }
        }
    }

    unsigned propertyCount = m_mutableStyle ? m_mutableStyle->propertyCount() : 0;
    for (unsigned i = 0; i < propertyCount; ++i) {
        CSSPropertyID propertyID = m_mutableStyle->propertyAt(i).id();

        // We don't override whitespace property of a tab span because that would collapse the tab into a space.
        if (propertyID == CSSPropertyWhiteSpace && isTabSpanNode(&element))
            continue;

        if (propertyID == CSSPropertyWebkitTextDecorationsInEffect && inlineStyle->getPropertyCSSValue(CSSPropertyTextDecoration)) {
            if (!newInlineStyle)
                return true;
            conflicts = true;
            newInlineStyle->removeProperty(CSSPropertyTextDecoration);
            if (extractedStyle)
                extractedStyle->setProperty(CSSPropertyTextDecoration, inlineStyle->getPropertyValue(CSSPropertyTextDecoration), inlineStyle->propertyIsImportant(CSSPropertyTextDecoration));
        }

        if (!inlineStyle->getPropertyCSSValue(propertyID))
            continue;

        if (propertyID == CSSPropertyUnicodeBidi && inlineStyle->getPropertyCSSValue(CSSPropertyDirection)) {
            if (!newInlineStyle)
                return true;
            conflicts = true;
            newInlineStyle->removeProperty(CSSPropertyDirection);
            if (extractedStyle)
                extractedStyle->setProperty(propertyID, inlineStyle->getPropertyValue(propertyID), inlineStyle->propertyIsImportant(propertyID));
        }

        if (!newInlineStyle)
            return true;

        conflicts = true;
        newInlineStyle->removeProperty(propertyID);
        if (extractedStyle)
            extractedStyle->setProperty(propertyID, inlineStyle->getPropertyValue(propertyID), inlineStyle->propertyIsImportant(propertyID));
    }

    return conflicts;
}

static Span<const HTMLElementEquivalent* const> htmlElementEquivalents()
{
    static const HTMLElementEquivalent* const equivalents[] = {
        new HTMLFontWeightEquivalent(HTMLNames::bTag),
        new HTMLFontWeightEquivalent(HTMLNames::strongTag),

        new HTMLElementEquivalent(CSSPropertyVerticalAlign, CSSValueSub, HTMLNames::subTag),
        new HTMLElementEquivalent(CSSPropertyVerticalAlign, CSSValueSuper, HTMLNames::supTag),
        new HTMLElementEquivalent(CSSPropertyFontStyle, CSSValueItalic, HTMLNames::iTag),
        new HTMLElementEquivalent(CSSPropertyFontStyle, CSSValueItalic, HTMLNames::emTag),

        new HTMLTextDecorationEquivalent(CSSValueUnderline, HTMLNames::uTag),
        new HTMLTextDecorationEquivalent(CSSValueLineThrough, HTMLNames::sTag),
        new HTMLTextDecorationEquivalent(CSSValueLineThrough, HTMLNames::strikeTag),
    };
    return equivalents;
}

bool EditingStyle::conflictsWithImplicitStyleOfElement(HTMLElement& element, EditingStyle* extractedStyle, ShouldExtractMatchingStyle shouldExtractMatchingStyle) const
{
    if (isEmpty())
        return false;

    for (auto& equivalent : htmlElementEquivalents()) {
        if (equivalent->matches(element) && equivalent->propertyExistsInStyle(*this)
            && (shouldExtractMatchingStyle == ExtractMatchingStyle || !equivalent->valueIsPresentInStyle(element, *this))) {
            if (extractedStyle)
                equivalent->addToStyle(&element, extractedStyle);
            return true;
        }
    }
    return false;
}

static Span<const HTMLAttributeEquivalent* const> htmlAttributeEquivalents()
{
    static const HTMLAttributeEquivalent* const equivalents[] = {
        // elementIsStyledSpanOrHTMLEquivalent depends on the fact each HTMLAttriuteEquivalent matches exactly one attribute
        // of exactly one element except dirAttr.
        new HTMLAttributeEquivalent(CSSPropertyColor, HTMLNames::fontTag, HTMLNames::colorAttr),
        new HTMLAttributeEquivalent(CSSPropertyFontFamily, HTMLNames::fontTag, HTMLNames::faceAttr),
        new HTMLFontSizeEquivalent,

        new HTMLAttributeEquivalent(CSSPropertyDirection, HTMLNames::dirAttr),
        new HTMLAttributeEquivalent(CSSPropertyUnicodeBidi, HTMLNames::dirAttr),
    };
    return equivalents;
}

bool EditingStyle::conflictsWithImplicitStyleOfAttributes(HTMLElement& element) const
{
    if (isEmpty())
        return false;

    for (auto& equivalent : htmlAttributeEquivalents()) {
        if (equivalent->matches(element) && equivalent->propertyExistsInStyle(*this) && !equivalent->valueIsPresentInStyle(element, *this))
            return true;
    }

    return false;
}

bool EditingStyle::extractConflictingImplicitStyleOfAttributes(HTMLElement& element, ShouldPreserveWritingDirection shouldPreserveWritingDirection,
    EditingStyle* extractedStyle, Vector<QualifiedName>& conflictingAttributes, ShouldExtractMatchingStyle shouldExtractMatchingStyle) const
{
    // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and direction properties
    ASSERT(!extractedStyle || shouldPreserveWritingDirection == PreserveWritingDirection);
    if (!m_mutableStyle)
        return false;

    bool removed = false;
    for (auto& equivalent : htmlAttributeEquivalents()) {
        // unicode-bidi and direction are pushed down separately so don't push down with other styles.
        if (shouldPreserveWritingDirection == PreserveWritingDirection && equivalent->attributeName() == HTMLNames::dirAttr)
            continue;

        if (!equivalent->matches(element) || !equivalent->propertyExistsInStyle(*this)
            || (shouldExtractMatchingStyle == DoNotExtractMatchingStyle && equivalent->valueIsPresentInStyle(element, *this)))
            continue;

        if (extractedStyle)
            equivalent->addToStyle(&element, extractedStyle);
        conflictingAttributes.append(equivalent->attributeName());
        removed = true;
    }

    return removed;
}

bool EditingStyle::styleIsPresentInComputedStyleOfNode(Node& node) const
{
    if (isEmpty())
        return true;
    ComputedStyleExtractor computedStyle(&node);

    bool shouldAddUnderline = underlineChange() == TextDecorationChange::Add;
    bool shouldAddLineThrough = strikeThroughChange() == TextDecorationChange::Add;
    if (shouldAddUnderline || shouldAddLineThrough) {
        bool hasUnderline = false;
        bool hasLineThrough = false;
        if (RefPtr<CSSValue> value = computedStyle.propertyValue(CSSPropertyTextDecoration)) {
            if (value->isValueList()) {
                auto& cssValuePool = CSSValuePool::singleton();
                const CSSValueList& valueList = downcast<CSSValueList>(*value);
                hasUnderline = valueList.hasValue(cssValuePool.createIdentifierValue(CSSValueUnderline).ptr());
                hasLineThrough = valueList.hasValue(cssValuePool.createIdentifierValue(CSSValueLineThrough).ptr());
            }
        }
        if ((shouldAddUnderline && !hasUnderline) || (shouldAddLineThrough && !hasLineThrough))
            return false;
    }

    return !m_mutableStyle || getPropertiesNotIn(*m_mutableStyle, computedStyle)->isEmpty();
}

bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement& element)
{
    bool elementIsSpanOrElementEquivalent = false;
    if (element.hasTagName(HTMLNames::spanTag))
        elementIsSpanOrElementEquivalent = true;
    else {
        for (auto& equivalent : htmlElementEquivalents()) {
            if (equivalent->matches(element)) {
                elementIsSpanOrElementEquivalent = true;
                break;
            }
        }
    }

    if (!element.hasAttributes())
        return elementIsSpanOrElementEquivalent; // span, b, etc... without any attributes

    unsigned matchedAttributes = 0;
    for (auto& equivalent : htmlAttributeEquivalents()) {
        if (equivalent->matches(element) && equivalent->attributeName() != HTMLNames::dirAttr)
            matchedAttributes++;
    }

    if (!elementIsSpanOrElementEquivalent && !matchedAttributes)
        return false; // element is not a span, a html element equivalent, or font element.
    
    if (element.attributeWithoutSynchronization(HTMLNames::classAttr) == AppleStyleSpanClass)
        matchedAttributes++;

    if (element.hasAttribute(HTMLNames::styleAttr)) {
        if (const StyleProperties* style = element.inlineStyle()) {
            unsigned propertyCount = style->propertyCount();
            for (unsigned i = 0; i < propertyCount; ++i) {
                if (!isEditingProperty(style->propertyAt(i).id()))
                    return false;
            }
        }
        matchedAttributes++;
    }

    // font with color attribute, span with style attribute, etc...
    ASSERT(matchedAttributes <= element.attributeCount());
    return matchedAttributes >= element.attributeCount();
}

void EditingStyle::prepareToApplyAt(const Position& position, ShouldPreserveWritingDirection shouldPreserveWritingDirection)
{
    if (!m_mutableStyle)
        return;

    // ReplaceSelectionCommand::handleStyleSpans() requires that this function only removes the editing style.
    // If this function was modified in the future to delete all redundant properties, then add a boolean value to indicate
    // which one of editingStyleAtPosition or computedStyle is called.
    auto editingStyleAtPosition = EditingStyle::create(position, EditingPropertiesInEffect);
    StyleProperties* styleAtPosition = editingStyleAtPosition->m_mutableStyle.get();

    RefPtr<CSSValue> unicodeBidi;
    RefPtr<CSSValue> direction;
    if (shouldPreserveWritingDirection == PreserveWritingDirection) {
        unicodeBidi = m_mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
        direction = m_mutableStyle->getPropertyCSSValue(CSSPropertyDirection);
    }

    removeEquivalentProperties(*styleAtPosition);

    if (textAlignResolvingStartAndEnd(*m_mutableStyle) == textAlignResolvingStartAndEnd(*styleAtPosition))
        m_mutableStyle->removeProperty(CSSPropertyTextAlign);

    if (equalIgnoringSemanticColor(textColorFromStyle(*m_mutableStyle), textColorFromStyle(*styleAtPosition)))
        m_mutableStyle->removeProperty(CSSPropertyColor);

    if (equalIgnoringSemanticColor(caretColorFromStyle(*m_mutableStyle), caretColorFromStyle(*styleAtPosition)))
        m_mutableStyle->removeProperty(CSSPropertyCaretColor);

    if (hasTransparentBackgroundColor(m_mutableStyle.get())
        || cssValueToColor(m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor).get()) == rgbaBackgroundColorInEffect(position.containerNode()))
        m_mutableStyle->removeProperty(CSSPropertyBackgroundColor);

    if (is<CSSPrimitiveValue>(unicodeBidi)) {
        m_mutableStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSValueID>(downcast<CSSPrimitiveValue>(*unicodeBidi).valueID()));
        if (is<CSSPrimitiveValue>(direction))
            m_mutableStyle->setProperty(CSSPropertyDirection, static_cast<CSSValueID>(downcast<CSSPrimitiveValue>(*direction).valueID()));
    }
}

void EditingStyle::mergeTypingStyle(Document& document)
{
    RefPtr<EditingStyle> typingStyle = document.frame()->selection().typingStyle();
    if (!typingStyle || typingStyle == this)
        return;

    mergeStyle(typingStyle->style(), OverrideValues);
}

void EditingStyle::mergeInlineStyleOfElement(StyledElement& element, CSSPropertyOverrideMode mode, PropertiesToInclude propertiesToInclude)
{
    if (!element.inlineStyle())
        return;

    switch (propertiesToInclude) {
    case AllProperties:
        mergeStyle(element.inlineStyle(), mode);
        return;
    case OnlyEditingInheritableProperties:
        mergeStyle(copyEditingProperties(element.inlineStyle(), OnlyInheritableEditingProperties).ptr(), mode);
        return;
    case EditingPropertiesInEffect:
        mergeStyle(copyEditingProperties(element.inlineStyle(), AllEditingProperties).ptr(), mode);
        return;
    }
}

static inline bool elementMatchesAndPropertyIsNotInInlineStyleDecl(const HTMLElementEquivalent& equivalent, const StyledElement& element,
    EditingStyle::CSSPropertyOverrideMode mode, EditingStyle& style)
{
    if (!equivalent.matches(element))
        return false;
    if (mode != EditingStyle::OverrideValues && equivalent.propertyExistsInStyle(style))
        return false;

    return !element.inlineStyle() || !equivalent.propertyExistsInStyle(EditingStyle::create(element.inlineStyle()).get());
}

static RefPtr<MutableStyleProperties> extractEditingProperties(const StyleProperties* style, EditingStyle::PropertiesToInclude propertiesToInclude)
{
    if (!style)
        return nullptr;

    switch (propertiesToInclude) {
    case EditingStyle::OnlyEditingInheritableProperties:
        return copyEditingProperties(style, OnlyInheritableEditingProperties);
    case EditingStyle::AllProperties:
    case EditingStyle::EditingPropertiesInEffect:
        break;
    }
    return copyEditingProperties(style, AllEditingProperties);
}

void EditingStyle::mergeInlineAndImplicitStyleOfElement(StyledElement& element, CSSPropertyOverrideMode mode, PropertiesToInclude propertiesToInclude, StandardFontFamilySerializationMode standardFontFamilySerializationMode)
{
    auto styleFromRules = EditingStyle::create();
    styleFromRules->mergeStyleFromRulesForSerialization(element, standardFontFamilySerializationMode);

    if (element.inlineStyle())
        styleFromRules->m_mutableStyle->mergeAndOverrideOnConflict(*element.inlineStyle());

    styleFromRules->m_mutableStyle = extractEditingProperties(styleFromRules->m_mutableStyle.get(), propertiesToInclude);
    mergeStyle(styleFromRules->m_mutableStyle.get(), mode);

    for (auto& equivalent : htmlElementEquivalents()) {
        if (elementMatchesAndPropertyIsNotInInlineStyleDecl(*equivalent, element, mode, *this))
            equivalent->addToStyle(&element, this);
    }

    for (auto& equivalent : htmlAttributeEquivalents()) {
        if (equivalent->attributeName() == HTMLNames::dirAttr)
            continue; // We don't want to include directionality
        if (elementMatchesAndPropertyIsNotInInlineStyleDecl(*equivalent, element, mode, *this))
            equivalent->addToStyle(&element, this);
    }
}

Ref<EditingStyle> EditingStyle::wrappingStyleForSerialization(Node& context, bool shouldAnnotate, StandardFontFamilySerializationMode standardFontFamilySerializationMode)
{
    if (shouldAnnotate) {
        auto wrappingStyle = EditingStyle::create(&context, EditingStyle::EditingPropertiesInEffect);

        // Styles that Mail blockquotes contribute should only be placed on the Mail blockquote,
        // to help us differentiate those styles from ones that the user has applied.
        // This helps us get the color of content pasted into blockquotes right.
        wrappingStyle->removeStyleAddedByNode(enclosingNodeOfType(firstPositionInOrBeforeNode(&context), isMailBlockquote, CanCrossEditingBoundary));

        // Call collapseTextDecorationProperties first or otherwise it'll copy the value over from in-effect to text-decorations.
        wrappingStyle->collapseTextDecorationProperties();
        
        return wrappingStyle;
    }

    auto wrappingStyle = EditingStyle::create();

    // When not annotating for interchange, we only preserve inline style declarations.
    for (Node* node = &context; node && !node->isDocumentNode(); node = node->parentNode()) {
        if (is<StyledElement>(*node) && !isMailBlockquote(node))
            wrappingStyle->mergeInlineAndImplicitStyleOfElement(downcast<StyledElement>(*node), DoNotOverrideValues, EditingPropertiesInEffect, standardFontFamilySerializationMode);
    }

    return wrappingStyle;
}


static void mergeTextDecorationValues(CSSValueList& mergedValue, const CSSValueList& valueToMerge)
{
    auto& cssValuePool = CSSValuePool::singleton();
    Ref<CSSPrimitiveValue> underline = cssValuePool.createIdentifierValue(CSSValueUnderline);
    Ref<CSSPrimitiveValue> lineThrough = cssValuePool.createIdentifierValue(CSSValueLineThrough);

    if (valueToMerge.hasValue(underline.ptr()) && !mergedValue.hasValue(underline.ptr()))
        mergedValue.append(WTFMove(underline));

    if (valueToMerge.hasValue(lineThrough.ptr()) && !mergedValue.hasValue(lineThrough.ptr()))
        mergedValue.append(WTFMove(lineThrough));
}

void EditingStyle::mergeStyle(const StyleProperties* style, CSSPropertyOverrideMode mode)
{
    if (!style)
        return;

    if (!m_mutableStyle) {
        m_mutableStyle = style->mutableCopy();
        return;
    }

    unsigned propertyCount = style->propertyCount();
    for (unsigned i = 0; i < propertyCount; ++i) {
        StyleProperties::PropertyReference property = style->propertyAt(i);
        RefPtr<CSSValue> value = m_mutableStyle->getPropertyCSSValue(property.id());

        // text decorations never override values.
        if ((property.id() == CSSPropertyTextDecoration || property.id() == CSSPropertyWebkitTextDecorationsInEffect)
            && is<CSSValueList>(*property.value()) && value) {
            if (is<CSSValueList>(*value)) {
                auto newValue = downcast<CSSValueList>(*value).copy();
                mergeTextDecorationValues(newValue, downcast<CSSValueList>(*property.value()));
                m_mutableStyle->setProperty(property.id(), WTFMove(newValue), property.isImportant());
                continue;
            }
            value = nullptr; // text-decoration: none is equivalent to not having the property.
        }

        if (mode == OverrideValues || (mode == DoNotOverrideValues && !value))
            m_mutableStyle->setProperty(property.id(), property.value(), property.isImportant());
    }

    int oldFontSizeDelta = m_fontSizeDelta;
    extractFontSizeDelta();
    m_fontSizeDelta += oldFontSizeDelta;
}

static Ref<MutableStyleProperties> styleFromMatchedRulesForElement(Element& element, unsigned rulesToInclude)
{
    auto style = MutableStyleProperties::create();
    for (auto& matchedRule : element.styleResolver().styleRulesForElement(&element, rulesToInclude))
        style->mergeAndOverrideOnConflict(matchedRule->properties());
    
    return style;
}

void EditingStyle::mergeStyleFromRules(StyledElement& element)
{
    RefPtr<MutableStyleProperties> styleFromMatchedRules = styleFromMatchedRulesForElement(element,
        Style::Resolver::AuthorCSSRules);
    // Styles from the inline style declaration, held in the variable "style", take precedence 
    // over those from matched rules.
    if (m_mutableStyle)
        styleFromMatchedRules->mergeAndOverrideOnConflict(*m_mutableStyle);

    clear();
    m_mutableStyle = styleFromMatchedRules;
}

static String familyNameFromCSSPrimitiveValue(const CSSPrimitiveValue& primitiveValue)
{
    if (!primitiveValue.isFontFamily())
        return { };
    return primitiveValue.fontFamily().familyName;
}

static String loneFontFamilyName(const CSSValue& value)
{
    if (is<CSSPrimitiveValue>(value))
        return familyNameFromCSSPrimitiveValue(downcast<CSSPrimitiveValue>(value));

    if (!is<CSSValueList>(value) || downcast<CSSValueList>(value).length() != 1)
        return { };

    auto& item = *downcast<CSSValueList>(value).item(0);
    if (!is<CSSPrimitiveValue>(item))
        return { };

    return familyNameFromCSSPrimitiveValue(downcast<CSSPrimitiveValue>(item));
}

void EditingStyle::mergeStyleFromRulesForSerialization(StyledElement& element, StandardFontFamilySerializationMode standardFontFamilySerializationMode)
{
    mergeStyleFromRules(element);

    // The property value, if it's a percentage, may not reflect the actual computed value.  
    // For example: style="height: 1%; overflow: visible;" in quirksmode
    // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot copy/paste fidelity problem
    auto fromComputedStyle = MutableStyleProperties::create();
    ComputedStyleExtractor computedStyle(&element);

    bool shouldRemoveFontFamily = false;
    {
        unsigned propertyCount = m_mutableStyle->propertyCount();
        for (unsigned i = 0; i < propertyCount; ++i) {
            StyleProperties::PropertyReference property = m_mutableStyle->propertyAt(i);
            CSSValue& value = *property.value();
            if (property.id() == CSSPropertyFontFamily) {
                auto familyName = loneFontFamilyName(value);
                if (FontCache::isSystemFontForbiddenForEditing(familyName)
                    || (standardFontFamilySerializationMode == StandardFontFamilySerializationMode::Strip && familyName == standardFamily))
                    shouldRemoveFontFamily = true;
                continue;
            }
            if (!is<CSSPrimitiveValue>(value))
                continue;
            if (downcast<CSSPrimitiveValue>(value).isPercentage()) {
                if (auto computedPropertyValue = computedStyle.propertyValue(property.id()))
                    fromComputedStyle->addParsedProperty(CSSProperty(property.id(), WTFMove(computedPropertyValue)));
            }
        }
    }
    if (shouldRemoveFontFamily) {
        m_mutableStyle->removeProperty(CSSPropertyFontFamily);
        fromComputedStyle->removeProperty(CSSPropertyFontFamily);
    }
    m_mutableStyle->mergeAndOverrideOnConflict(fromComputedStyle.get());
}

static void removePropertiesInStyle(MutableStyleProperties* styleToRemovePropertiesFrom, MutableStyleProperties* style)
{
    unsigned propertyCount = style->propertyCount();
    Vector<CSSPropertyID> propertiesToRemove(propertyCount);
    for (unsigned i = 0; i < propertyCount; ++i)
        propertiesToRemove[i] = style->propertyAt(i).id();

    styleToRemovePropertiesFrom->removePropertiesInSet(propertiesToRemove.data(), propertiesToRemove.size());
}

void EditingStyle::removeStyleFromRulesAndContext(StyledElement& element, Node* context)
{
    if (!m_mutableStyle)
        return;

    // 1. Remove style from matched rules because style remain without repeating it in inline style declaration
    RefPtr<MutableStyleProperties> styleFromMatchedRules = styleFromMatchedRulesForElement(element, Style::Resolver::AllButEmptyCSSRules);
    if (styleFromMatchedRules && !styleFromMatchedRules->isEmpty())
        m_mutableStyle = getPropertiesNotIn(*m_mutableStyle, *styleFromMatchedRules);

    // 2. Remove style present in context and not overridden by matched rules.
    auto computedStyle = EditingStyle::create(context, EditingPropertiesInEffect);
    if (computedStyle->m_mutableStyle) {
        if (!computedStyle->m_mutableStyle->getPropertyCSSValue(CSSPropertyBackgroundColor))
            computedStyle->m_mutableStyle->setProperty(CSSPropertyBackgroundColor, CSSValueTransparent);

        RefPtr<EditingStyle> computedStyleOfElement;
        auto replaceSemanticColorWithComputedValue = [&](const CSSPropertyID id) {
            auto color = m_mutableStyle->propertyAsColor(id);
            if (!color || (color->isVisible() && !color->isSemantic()))
                return;

            if (!computedStyleOfElement)
                computedStyleOfElement = EditingStyle::create(&element, EditingPropertiesInEffect);

            if (!computedStyleOfElement->m_mutableStyle)
                return;

            auto computedValue = computedStyleOfElement->m_mutableStyle->getPropertyValue(id);
            if (!computedValue)
                return;

            m_mutableStyle->setProperty(id, computedValue);
        };

        // Replace semantic color identifiers like -apple-system-label with RGB values so that comparsions in getPropertiesNotIn below would work.
        replaceSemanticColorWithComputedValue(CSSPropertyColor);
        replaceSemanticColorWithComputedValue(CSSPropertyCaretColor);
        replaceSemanticColorWithComputedValue(CSSPropertyBackgroundColor);

        removePropertiesInStyle(computedStyle->m_mutableStyle.get(), styleFromMatchedRules.get());
        m_mutableStyle = getPropertiesNotIn(*m_mutableStyle, *computedStyle->m_mutableStyle);
    }

    // 3. If this element is a span and has display: inline or float: none, remove them unless they are overridden by rules.
    // These rules are added by serialization code to wrap text nodes.
    if (isStyleSpanOrSpanWithOnlyStyleAttribute(element)) {
        if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyDisplay) && identifierForStyleProperty(*m_mutableStyle, CSSPropertyDisplay) == CSSValueInline)
            m_mutableStyle->removeProperty(CSSPropertyDisplay);
        if (!styleFromMatchedRules->getPropertyCSSValue(CSSPropertyFloat) && identifierForStyleProperty(*m_mutableStyle, CSSPropertyFloat) == CSSValueNone)
            m_mutableStyle->removeProperty(CSSPropertyFloat);
    }
}

void EditingStyle::removePropertiesInElementDefaultStyle(Element& element)
{
    if (!m_mutableStyle || m_mutableStyle->isEmpty())
        return;

    RefPtr<MutableStyleProperties> defaultStyle = styleFromMatchedRulesForElement(element, Style::Resolver::UAAndUserCSSRules);

    removePropertiesInStyle(m_mutableStyle.get(), defaultStyle.get());
}

template<typename T>
void EditingStyle::removeEquivalentProperties(T& style)
{
    Vector<CSSPropertyID> propertiesToRemove;
    for (auto& property : m_mutableStyle->m_propertyVector) {
        if (style.propertyMatches(property.id(), property.value()))
            propertiesToRemove.append(property.id());
    }
    // FIXME: This should use mass removal.
    for (auto& property : propertiesToRemove)
        m_mutableStyle->removeProperty(property);
}

void EditingStyle::forceInline()
{
    if (!m_mutableStyle)
        m_mutableStyle = MutableStyleProperties::create();
    const bool propertyIsImportant = true;
    m_mutableStyle->setProperty(CSSPropertyDisplay, CSSValueInline, propertyIsImportant);
}

void EditingStyle::addDisplayContents()
{
    if (!m_mutableStyle)
        m_mutableStyle = MutableStyleProperties::create();
    m_mutableStyle->setProperty(CSSPropertyDisplay, CSSValueContents);
}

bool EditingStyle::convertPositionStyle()
{
    if (!m_mutableStyle)
        return false;

    auto& cssValuePool = CSSValuePool::singleton();
    RefPtr<CSSPrimitiveValue> sticky = cssValuePool.createIdentifierValue(CSSValueSticky);
    if (m_mutableStyle->propertyMatches(CSSPropertyPosition, sticky.get())) {
        m_mutableStyle->setProperty(CSSPropertyPosition, cssValuePool.createIdentifierValue(CSSValueStatic), m_mutableStyle->propertyIsImportant(CSSPropertyPosition));
        return false;
    }
    RefPtr<CSSPrimitiveValue> fixed = cssValuePool.createIdentifierValue(CSSValueFixed);
    if (m_mutableStyle->propertyMatches(CSSPropertyPosition, fixed.get())) {
        m_mutableStyle->setProperty(CSSPropertyPosition, cssValuePool.createIdentifierValue(CSSValueAbsolute), m_mutableStyle->propertyIsImportant(CSSPropertyPosition));
        return true;
    }
    RefPtr<CSSPrimitiveValue> absolute = cssValuePool.createIdentifierValue(CSSValueAbsolute);
    if (m_mutableStyle->propertyMatches(CSSPropertyPosition, absolute.get()))
        return true;
    return false;
}

bool EditingStyle::isFloating()
{
    RefPtr<CSSValue> v = m_mutableStyle->getPropertyCSSValue(CSSPropertyFloat);
    RefPtr<CSSPrimitiveValue> noneValue = CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
    return v && !v->equals(*noneValue);
}

int EditingStyle::legacyFontSize(Document& document) const
{
    RefPtr<CSSValue> cssValue = m_mutableStyle->getPropertyCSSValue(CSSPropertyFontSize);
    if (!is<CSSPrimitiveValue>(cssValue))
        return 0;
    return legacyFontSizeFromCSSValue(document, downcast<CSSPrimitiveValue>(cssValue.get()),
        m_shouldUseFixedDefaultFontSize, AlwaysUseLegacyFontSize);
}

bool EditingStyle::hasStyle(CSSPropertyID propertyID, const String& value)
{
    return EditingStyle::create(propertyID, value)->triStateOfStyle(this) != TriState::False;
}

RefPtr<EditingStyle> EditingStyle::styleAtSelectionStart(const VisibleSelection& selection, bool shouldUseBackgroundColorInEffect)
{
    if (selection.isNone())
        return nullptr;

    Position position = adjustedSelectionStartForStyleComputation(selection);

    // If the pos is at the end of a text node, then this node is not fully selected. 
    // Move it to the next deep equivalent position to avoid removing the style from this node. 
    // e.g. if pos was at Position("hello", 5) in <b>hello<div>world</div></b>, we want Position("world", 0) instead. 
    // We only do this for range because caret at Position("hello", 5) in <b>hello</b>world should give you font-weight: bold. 
    Node* positionNode = position.containerNode(); 
    if (selection.isRange() && is<Text>(positionNode) && static_cast<unsigned>(position.computeOffsetInContainerNode()) == downcast<Text>(*positionNode).length())
        position = nextVisuallyDistinctCandidate(position);

    Element* element = position.element();
    if (!element)
        return nullptr;

    auto style = EditingStyle::create(element, EditingStyle::AllProperties);
    style->mergeTypingStyle(element->document());

    // If background color is transparent, traverse parent nodes until we hit a different value or document root
    // Also, if the selection is a range, ignore the background color at the start of selection,
    // and find the background color of the common ancestor.
    if (shouldUseBackgroundColorInEffect && (selection.isRange() || hasTransparentBackgroundColor(style->m_mutableStyle.get()))) {
        if (auto range = selection.toNormalizedRange()) {
            if (auto value = backgroundColorInEffect(commonInclusiveAncestor<ComposedTree>(*range)))
                style->setProperty(CSSPropertyBackgroundColor, value->cssText());
        }
    }

    return style;
}

WritingDirection EditingStyle::textDirectionForSelection(const VisibleSelection& selection, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings)
{
    hasNestedOrMultipleEmbeddings = true;

    if (selection.isNone())
        return WritingDirection::Natural;

    Position position = selection.start().downstream();

    Node* node = position.deprecatedNode();
    if (!node)
        return WritingDirection::Natural;

    Position end;
    if (selection.isRange()) {
        end = selection.end().upstream();
        for (auto& intersectingNode : intersectingNodes(*makeSimpleRange(position, end))) {
            if (!intersectingNode.isStyledElement())
                continue;
            auto valueObject = ComputedStyleExtractor(&intersectingNode).propertyValue(CSSPropertyUnicodeBidi);
            auto value = is<CSSPrimitiveValue>(valueObject) ? downcast<CSSPrimitiveValue>(*valueObject).valueID() : CSSValueInvalid;
            if (value == CSSValueEmbed || value == CSSValueBidiOverride)
                return WritingDirection::Natural;
        }
    }

    if (selection.isCaret()) {
        if (typingStyle) {
            if (auto direction = typingStyle->textDirection()) {
                hasNestedOrMultipleEmbeddings = false;
                return *direction;
            }
        }
        node = selection.visibleStart().deepEquivalent().deprecatedNode();
    }

    // The selection is either a caret with no typing attributes or a range in which no embedding is added, so just use the start position
    // to decide.
    Node* block = enclosingBlock(node);
    auto foundDirection = WritingDirection::Natural;

    for (; node != block; node = node->parentNode()) {
        if (!node->isStyledElement())
            continue;

        ComputedStyleExtractor computedStyle(node);
        RefPtr<CSSValue> unicodeBidi = computedStyle.propertyValue(CSSPropertyUnicodeBidi);
        if (!is<CSSPrimitiveValue>(unicodeBidi))
            continue;

        CSSValueID unicodeBidiValue = downcast<CSSPrimitiveValue>(*unicodeBidi).valueID();
        if (unicodeBidiValue == CSSValueNormal)
            continue;

        if (unicodeBidiValue == CSSValueBidiOverride)
            return WritingDirection::Natural;

        ASSERT(unicodeBidiValue == CSSValueEmbed);
        RefPtr<CSSValue> direction = computedStyle.propertyValue(CSSPropertyDirection);
        if (!is<CSSPrimitiveValue>(direction))
            continue;

        CSSValueID directionValue = downcast<CSSPrimitiveValue>(*direction).valueID();
        if (directionValue != CSSValueLtr && directionValue != CSSValueRtl)
            continue;

        if (foundDirection != WritingDirection::Natural)
            return WritingDirection::Natural;

        // In the range case, make sure that the embedding element persists until the end of the range.
        if (selection.isRange() && !end.deprecatedNode()->isDescendantOf(*node))
            return WritingDirection::Natural;
        
        foundDirection = directionValue == CSSValueLtr ? WritingDirection::LeftToRight : WritingDirection::RightToLeft;
    }
    hasNestedOrMultipleEmbeddings = false;
    return foundDirection;
}

Ref<EditingStyle> EditingStyle::inverseTransformColorIfNeeded(Element& element)
{
    auto* renderer = element.renderer();
    if (!m_mutableStyle || !renderer || !renderer->style().hasAppleColorFilter())
        return *this;

    auto colorForPropertyIfInvertible = [&](CSSPropertyID id) -> std::optional<Color> {
        auto color = m_mutableStyle->propertyAsColor(id);
        if (!color || !color->isVisible() || color->isSemantic())
            return std::nullopt;
        return color;
    };

    auto color = colorForPropertyIfInvertible(CSSPropertyColor);
    auto caretColor = colorForPropertyIfInvertible(CSSPropertyCaretColor);
    auto backgroundColor = colorForPropertyIfInvertible(CSSPropertyBackgroundColor);
    if (!color && !caretColor && !backgroundColor)
        return *this;

    auto styleWithInvertedColors = copy();
    ASSERT(styleWithInvertedColors->m_mutableStyle);

    const auto& colorFilter = renderer->style().appleColorFilter();
    auto invertedColor = [&](CSSPropertyID propertyID) {
        Color newColor = cssValueToColor(extractPropertyValue(*m_mutableStyle, propertyID).get());
        colorFilter.inverseTransformColor(newColor);
        styleWithInvertedColors->m_mutableStyle->setProperty(propertyID, serializationForCSS(newColor));
    };

    if (color)
        invertedColor(CSSPropertyColor);

    if (caretColor)
        invertedColor(CSSPropertyCaretColor);

    if (backgroundColor)
        invertedColor(CSSPropertyBackgroundColor);

    return styleWithInvertedColors;
}

static void reconcileTextDecorationProperties(MutableStyleProperties* style)
{    
    RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
    // We shouldn't have both text-decoration and -webkit-text-decorations-in-effect because that wouldn't make sense.
    ASSERT(!textDecorationsInEffect || !textDecoration);
    if (textDecorationsInEffect) {
        style->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText());
        style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
        textDecoration = textDecorationsInEffect;
    }

    // If text-decoration is set to "none", remove the property because we don't want to add redundant "text-decoration: none".
    if (textDecoration && !textDecoration->isValueList())
        style->removeProperty(CSSPropertyTextDecoration);
}

StyleChange::StyleChange(EditingStyle* style, const Position& position)
    : m_applyBold(false)
    , m_applyItalic(false)
    , m_applyUnderline(false)
    , m_applyLineThrough(false)
    , m_applySubscript(false)
    , m_applySuperscript(false)
{
    Document* document = position.deprecatedNode() ? &position.deprecatedNode()->document() : 0;
    if (!style || style->isEmpty() || !document || !document->frame())
        return;

    Node* node = position.containerNode();
    if (!node)
        return;

    ComputedStyleExtractor computedStyle(node);

    // FIXME: take care of background-color in effect
    RefPtr<MutableStyleProperties> mutableStyle = style->style() ?
        getPropertiesNotIn(*style->style(), computedStyle) : MutableStyleProperties::create();

    reconcileTextDecorationProperties(mutableStyle.get());
    bool shouldStyleWithCSS = document->editor().shouldStyleWithCSS();
    if (!shouldStyleWithCSS)
        extractTextStyles(*document, *mutableStyle, computedStyle.useFixedFontDefaultSize());

    bool shouldAddUnderline = style->underlineChange() == TextDecorationChange::Add;
    bool shouldAddStrikeThrough = style->strikeThroughChange() == TextDecorationChange::Add;
    if (shouldAddUnderline || shouldAddStrikeThrough) {
        RefPtr<CSSValue> value = computedStyle.propertyValue(CSSPropertyWebkitTextDecorationsInEffect);
        if (!is<CSSValueList>(value))
            value = computedStyle.propertyValue(CSSPropertyTextDecoration);

        RefPtr<CSSValueList> valueList;
        if (is<CSSValueList>(value))
            valueList = downcast<CSSValueList>(value.get());

        auto& cssValuePool = CSSValuePool::singleton();
        Ref<CSSValue> underline = cssValuePool.createIdentifierValue(CSSValueUnderline);
        bool hasUnderline = valueList && valueList->hasValue(underline.ptr());

        Ref<CSSValue> lineThrough = cssValuePool.createIdentifierValue(CSSValueLineThrough);
        bool hasLineThrough = valueList && valueList->hasValue(lineThrough.ptr());

        if (shouldStyleWithCSS) {
            valueList = valueList ? valueList->copy() : CSSValueList::createSpaceSeparated();
            if (shouldAddUnderline && !hasUnderline)
                valueList->append(WTFMove(underline));
            if (shouldAddStrikeThrough && !hasLineThrough)
                valueList->append(WTFMove(lineThrough));
            mutableStyle->setProperty(CSSPropertyTextDecoration, valueList.get());
        } else {
            m_applyUnderline = shouldAddUnderline && !hasUnderline;
            m_applyLineThrough = shouldAddStrikeThrough && !hasLineThrough;
        }
    }

    // Changing the whitespace style in a tab span would collapse the tab into a space.
    if (isTabSpanTextNode(position.deprecatedNode()) || isTabSpanNode((position.deprecatedNode())))
        mutableStyle->removeProperty(CSSPropertyWhiteSpace);

    // If unicode-bidi is present in mutableStyle and direction is not, then add direction to mutableStyle.
    // FIXME: Shouldn't this be done in getPropertiesNotIn?
    if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->style()->getPropertyCSSValue(CSSPropertyDirection))
        mutableStyle->setProperty(CSSPropertyDirection, style->style()->getPropertyValue(CSSPropertyDirection));

    if (!mutableStyle->isEmpty())
        m_cssStyle = mutableStyle;
}

bool StyleChange::operator==(const StyleChange& other)
{
    if (m_applyBold != other.m_applyBold
        || m_applyItalic != other.m_applyItalic
        || m_applyUnderline != other.m_applyUnderline
        || m_applyLineThrough != other.m_applyLineThrough
        || m_applySubscript != other.m_applySubscript
        || m_applySuperscript != other.m_applySuperscript
        || m_applyFontColor != other.m_applyFontColor
        || m_applyFontFace != other.m_applyFontFace
        || m_applyFontSize != other.m_applyFontSize)
        return false;

    return (!m_cssStyle && !other.m_cssStyle)
        || (m_cssStyle && other.m_cssStyle && m_cssStyle->asText() == other.m_cssStyle->asText());
}

static void setTextDecorationProperty(MutableStyleProperties& style, const CSSValueList* newTextDecoration, CSSPropertyID propertyID)
{
    if (newTextDecoration->length())
        style.setProperty(propertyID, newTextDecoration->cssText(), style.propertyIsImportant(propertyID));
    else {
        // text-decoration: none is redundant since it does not remove any text decorations.
        style.removeProperty(propertyID);
    }
}

void StyleChange::extractTextStyles(Document& document, MutableStyleProperties& style, bool shouldUseFixedFontDefaultSize)
{
    if (identifierForStyleProperty(style, CSSPropertyFontWeight) == CSSValueBold) {
        style.removeProperty(CSSPropertyFontWeight);
        m_applyBold = true;
    }

    int fontStyle = identifierForStyleProperty(style, CSSPropertyFontStyle);
    if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) {
        style.removeProperty(CSSPropertyFontStyle);
        m_applyItalic = true;
    }

    // Assuming reconcileTextDecorationProperties has been called, there should not be -webkit-text-decorations-in-effect
    // Furthermore, text-decoration: none has been trimmed so that text-decoration property is always a CSSValueList.
    RefPtr<CSSValue> textDecoration = style.getPropertyCSSValue(CSSPropertyTextDecoration);
    if (is<CSSValueList>(textDecoration)) {
        auto& cssValuePool = CSSValuePool::singleton();
        RefPtr<CSSPrimitiveValue> underline = cssValuePool.createIdentifierValue(CSSValueUnderline);
        RefPtr<CSSPrimitiveValue> lineThrough = cssValuePool.createIdentifierValue(CSSValueLineThrough);

        RefPtr<CSSValueList> newTextDecoration = downcast<CSSValueList>(*textDecoration).copy();
        if (newTextDecoration->removeAll(underline.get()))
            m_applyUnderline = true;
        if (newTextDecoration->removeAll(lineThrough.get()))
            m_applyLineThrough = true;

        // If trimTextDecorations, delete underline and line-through
        setTextDecorationProperty(style, newTextDecoration.get(), CSSPropertyTextDecoration);
    }

    int verticalAlign = identifierForStyleProperty(style, CSSPropertyVerticalAlign);
    switch (verticalAlign) {
    case CSSValueSub:
        style.removeProperty(CSSPropertyVerticalAlign);
        m_applySubscript = true;
        break;
    case CSSValueSuper:
        style.removeProperty(CSSPropertyVerticalAlign);
        m_applySuperscript = true;
        break;
    }

    if (style.getPropertyCSSValue(CSSPropertyColor)) {
        auto color = textColorFromStyle(style);
        if (color.isOpaque()) {
            m_applyFontColor = serializationForHTML(color);
            style.removeProperty(CSSPropertyColor);
        }
    }

    m_applyFontFace = style.getPropertyValue(CSSPropertyFontFamily);
    // Remove quotes for Outlook 2007 compatibility. See https://bugs.webkit.org/show_bug.cgi?id=79448
    m_applyFontFace.replaceWithLiteral('\"', "");
    style.removeProperty(CSSPropertyFontFamily);

    if (RefPtr<CSSValue> fontSize = style.getPropertyCSSValue(CSSPropertyFontSize)) {
        if (!is<CSSPrimitiveValue>(*fontSize))
            style.removeProperty(CSSPropertyFontSize); // Can't make sense of the number. Put no font size.
        else if (int legacyFontSize = legacyFontSizeFromCSSValue(document, downcast<CSSPrimitiveValue>(fontSize.get()),
                shouldUseFixedFontDefaultSize, UseLegacyFontSizeOnlyIfPixelValuesMatch)) {
            m_applyFontSize = String::number(legacyFontSize);
            style.removeProperty(CSSPropertyFontSize);
        }
    }
}

static void diffTextDecorations(MutableStyleProperties& style, CSSPropertyID propertID, CSSValue* refTextDecoration)
{
    RefPtr<CSSValue> textDecoration = style.getPropertyCSSValue(propertID);
    if (!is<CSSValueList>(textDecoration) || !is<CSSValueList>(refTextDecoration))
        return;

    RefPtr<CSSValueList> newTextDecoration = downcast<CSSValueList>(*textDecoration).copy();

    for (auto& value :  downcast<CSSValueList>(*refTextDecoration))
        newTextDecoration->removeAll(&value.get());

    setTextDecorationProperty(style, newTextDecoration.get(), propertID);
}

template<typename T>
static bool fontWeightIsBold(T& style)
{
    RefPtr<CSSValue> fontWeight = extractPropertyValue(style, CSSPropertyFontWeight);
    return fontWeight && fontWeightIsBold(*fontWeight);
}

template<typename T>
static Ref<MutableStyleProperties> extractPropertiesNotIn(StyleProperties& styleWithRedundantProperties, T& baseStyle)
{
    auto result = EditingStyle::create(&styleWithRedundantProperties);
    result->removeEquivalentProperties(baseStyle);
    ASSERT(result->style());
    Ref<MutableStyleProperties> mutableStyle = *result->style();

    RefPtr<CSSValue> baseTextDecorationsInEffect = extractPropertyValue(baseStyle, CSSPropertyWebkitTextDecorationsInEffect);
    diffTextDecorations(mutableStyle, CSSPropertyTextDecoration, baseTextDecorationsInEffect.get());
    diffTextDecorations(mutableStyle, CSSPropertyWebkitTextDecorationsInEffect, baseTextDecorationsInEffect.get());

    if (extractPropertyValue(baseStyle, CSSPropertyFontWeight) && fontWeightIsBold(mutableStyle) == fontWeightIsBold(baseStyle))
        mutableStyle->removeProperty(CSSPropertyFontWeight);

    if (extractPropertyValue(baseStyle, CSSPropertyColor) && equalIgnoringSemanticColor(textColorFromStyle(mutableStyle), textColorFromStyle(baseStyle)))
        mutableStyle->removeProperty(CSSPropertyColor);

    if (extractPropertyValue(baseStyle, CSSPropertyCaretColor) && equalIgnoringSemanticColor(caretColorFromStyle(mutableStyle), caretColorFromStyle(baseStyle)))
        mutableStyle->removeProperty(CSSPropertyCaretColor);

    if (extractPropertyValue(baseStyle, CSSPropertyTextAlign)
        && textAlignResolvingStartAndEnd(mutableStyle) == textAlignResolvingStartAndEnd(baseStyle))
        mutableStyle->removeProperty(CSSPropertyTextAlign);

    if (extractPropertyValue(baseStyle, CSSPropertyBackgroundColor) && equalIgnoringSemanticColor(backgroundColorFromStyle(mutableStyle), backgroundColorFromStyle(baseStyle)))
        mutableStyle->removeProperty(CSSPropertyBackgroundColor);

    return mutableStyle;
}

template<typename T>
Ref<MutableStyleProperties> getPropertiesNotIn(StyleProperties& styleWithRedundantProperties, T& baseStyle)
{
    return extractPropertiesNotIn(styleWithRedundantProperties, baseStyle);
}

static bool isCSSValueLength(CSSPrimitiveValue* value)
{
    return value->isFontIndependentLength();
}

int legacyFontSizeFromCSSValue(Document& document, CSSPrimitiveValue* value, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode mode)
{
    if (isCSSValueLength(value)) {
        int pixelFontSize = value->intValue(CSSUnitType::CSS_PX);
        int legacyFontSize = Style::legacyFontSizeForPixelSize(pixelFontSize, shouldUseFixedFontDefaultSize, document);
        // Use legacy font size only if pixel value matches exactly to that of legacy font size.
        int cssPrimitiveEquivalent = legacyFontSize - 1 + CSSValueXSmall;
        if (mode == AlwaysUseLegacyFontSize || Style::fontSizeForKeyword(cssPrimitiveEquivalent, shouldUseFixedFontDefaultSize, document) == pixelFontSize)
            return legacyFontSize;

        return 0;
    }

    if (CSSValueXSmall <= value->valueID() && value->valueID() <= CSSValueWebkitXxxLarge)
        return value->valueID() - CSSValueXSmall + 1;

    return 0;
}

static bool isTransparentColorValue(CSSValue* value)
{
    if (!value)
        return true;
    if (!is<CSSPrimitiveValue>(*value))
        return false;
    auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
    if (primitiveValue.isRGBColor())
        return !primitiveValue.color().isVisible();
    return primitiveValue.valueID() == CSSValueTransparent;
}

bool hasTransparentBackgroundColor(StyleProperties* style)
{
    return isTransparentColorValue(style->getPropertyCSSValue(CSSPropertyBackgroundColor).get());
}

RefPtr<CSSValue> backgroundColorInEffect(Node* node)
{
    for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) {
        if (auto value = ComputedStyleExtractor(ancestor).propertyValue(CSSPropertyBackgroundColor)) {
            if (!isTransparentColorValue(value.get()))
                return value;
        }
    }
    return nullptr;
}

}
