/*
 * Copyright (C) 2007, 2008, 2009 Apple Computer, 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 "third_party/blink/renderer/core/editing/editing_style.h"

#include "base/stl_util.h"
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/css_style_rule.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/font_size_functions.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/editing/commands/apply_style_command.h"
#include "third_party/blink/renderer/core/editing/editing_style_utilities.h"
#include "third_party/blink/renderer/core/editing/editing_tri_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/serializers/html_interchange.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_font_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"

namespace blink {

// 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.
// NOTE: Use either allEditingProperties() or inheritableEditingProperties() to
// respect runtime enabling of properties.
static const CSSPropertyID kStaticEditingProperties[] = {
    CSSPropertyID::kBackgroundColor, CSSPropertyID::kColor,
    CSSPropertyID::kFontFamily, CSSPropertyID::kFontSize,
    CSSPropertyID::kFontStyle, CSSPropertyID::kFontVariantLigatures,
    CSSPropertyID::kFontVariantCaps, CSSPropertyID::kFontWeight,
    CSSPropertyID::kLetterSpacing, CSSPropertyID::kOrphans,
    CSSPropertyID::kTextAlign,
    // FIXME: CSSPropertyID::kTextDecoration needs to be removed when CSS3 Text
    // Decoration feature is no longer experimental.
    CSSPropertyID::kTextDecoration, CSSPropertyID::kTextDecorationLine,
    CSSPropertyID::kTextIndent, CSSPropertyID::kTextTransform,
    CSSPropertyID::kWhiteSpace, CSSPropertyID::kWidows,
    CSSPropertyID::kWordSpacing, CSSPropertyID::kWebkitTextDecorationsInEffect,
    CSSPropertyID::kWebkitTextFillColor, CSSPropertyID::kWebkitTextStrokeColor,
    CSSPropertyID::kWebkitTextStrokeWidth, CSSPropertyID::kCaretColor};

enum EditingPropertiesType {
  kOnlyInheritableEditingProperties,
  kAllEditingProperties
};

static const Vector<const CSSProperty*>& AllEditingProperties(
    const ExecutionContext* execution_context) {
  DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ());
  if (properties.IsEmpty()) {
    CSSProperty::FilterWebExposedCSSPropertiesIntoVector(
        execution_context, kStaticEditingProperties,
        base::size(kStaticEditingProperties), properties);
    for (wtf_size_t index = 0; index < properties.size(); index++) {
      if (properties[index]->IDEquals(CSSPropertyID::kTextDecoration)) {
        properties.EraseAt(index);
        break;
      }
    }
  }
  return properties;
}

static const Vector<const CSSProperty*>& InheritableEditingProperties(
    const ExecutionContext* execution_context) {
  DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ());
  if (properties.IsEmpty()) {
    CSSProperty::FilterWebExposedCSSPropertiesIntoVector(
        execution_context, kStaticEditingProperties,
        base::size(kStaticEditingProperties), properties);
    for (wtf_size_t index = 0; index < properties.size();) {
      if (!properties[index]->IsInherited()) {
        properties.EraseAt(index);
        continue;
      }
      ++index;
    }
  }
  return properties;
}

template <class StyleDeclarationType>
static MutableCSSPropertyValueSet* CopyEditingProperties(
    const ExecutionContext* execution_context,
    StyleDeclarationType* style,
    EditingPropertiesType type = kOnlyInheritableEditingProperties) {
  if (type == kAllEditingProperties)
    return style->CopyPropertiesInSet(AllEditingProperties(execution_context));
  return style->CopyPropertiesInSet(
      InheritableEditingProperties(execution_context));
}

static inline bool IsEditingProperty(ExecutionContext* execution_context,
                                     CSSPropertyID id) {
  static const Vector<const CSSProperty*>& properties =
      AllEditingProperties(execution_context);
  for (wtf_size_t index = 0; index < properties.size(); index++) {
    if (properties[index]->IDEquals(id))
      return true;
  }
  return false;
}

static MutableCSSPropertyValueSet* GetPropertiesNotIn(
    CSSPropertyValueSet* style_with_redundant_properties,
    Node*,
    CSSStyleDeclaration* base_style,
    SecureContextMode);
enum LegacyFontSizeMode {
  kAlwaysUseLegacyFontSize,
  kUseLegacyFontSizeOnlyIfPixelValuesMatch
};
static int LegacyFontSizeFromCSSValue(Document*,
                                      const CSSValue*,
                                      bool,
                                      LegacyFontSizeMode);

class HTMLElementEquivalent : public GarbageCollected<HTMLElementEquivalent> {
 public:
  HTMLElementEquivalent(CSSPropertyID);
  HTMLElementEquivalent(CSSPropertyID, const HTMLQualifiedName& tag_name);
  HTMLElementEquivalent(CSSPropertyID,
                        CSSValueID primitive_value,
                        const HTMLQualifiedName& tag_name);

  virtual bool Matches(const Element* element) const {
    return !tag_name_ || element->HasTagName(*tag_name_);
  }
  virtual bool HasAttribute() const { return false; }
  virtual bool PropertyExistsInStyle(const CSSPropertyValueSet* style) const {
    return style->GetPropertyCSSValue(property_id_);
  }
  virtual bool ValueIsPresentInStyle(HTMLElement*, CSSPropertyValueSet*) const;
  virtual void AddToStyle(Element*, EditingStyle*) const;

  virtual void Trace(Visitor* visitor) const {
    visitor->Trace(identifier_value_);
  }

 protected:
  const CSSPropertyID property_id_;
  const Member<CSSIdentifierValue> identifier_value_;
  // We can store a pointer because HTML tag names are const global.
  const HTMLQualifiedName* tag_name_;
};

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id)
    : property_id_(id), tag_name_(nullptr) {}

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id,
                                             const HTMLQualifiedName& tag_name)
    : property_id_(id), tag_name_(&tag_name) {}

HTMLElementEquivalent::HTMLElementEquivalent(CSSPropertyID id,
                                             CSSValueID value_id,
                                             const HTMLQualifiedName& tag_name)
    : property_id_(id),
      identifier_value_(CSSIdentifierValue::Create(value_id)),
      tag_name_(&tag_name) {
  DCHECK(IsValidCSSValueID(value_id));
}

bool HTMLElementEquivalent::ValueIsPresentInStyle(
    HTMLElement* element,
    CSSPropertyValueSet* style) const {
  const CSSValue* value = style->GetPropertyCSSValue(property_id_);

  // TODO: Does this work on style or computed style? The code here, but we
  // might need to do something here to match CSSPrimitiveValues. if
  // (property_id_ == CSSPropertyID::kFontWeight &&
  //     identifier_value_->GetValueID() == CSSValueID::kBold) {
  //   auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value);
  //   if (primitive_value &&
  //       primitive_value->GetFloatValue() >= BoldThreshold()) {
  //     LOG(INFO) << "weight match in HTMLElementEquivalent for primitive
  //     value"; return true;
  //   } else {
  //     LOG(INFO) << "weight match in HTMLElementEquivalent for identifier
  //     value";
  //   }
  // }

  if (!Matches(element))
    return false;

  auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
  return identifier_value &&
         identifier_value->GetValueID() == identifier_value_->GetValueID();
}

void HTMLElementEquivalent::AddToStyle(Element* element,
                                       EditingStyle* style) const {
  style->SetProperty(property_id_, identifier_value_->CssText(),
                     /* important */ false,
                     element->GetExecutionContext()->GetSecureContextMode());
}

class HTMLTextDecorationEquivalent final : public HTMLElementEquivalent {
 public:
  static HTMLElementEquivalent* Create(CSSValueID primitive_value,
                                       const HTMLQualifiedName& tag_name) {
    return MakeGarbageCollected<HTMLTextDecorationEquivalent>(primitive_value,
                                                              tag_name);
  }

  HTMLTextDecorationEquivalent(CSSValueID primitive_value,
                               const HTMLQualifiedName& tag_name);

  bool PropertyExistsInStyle(const CSSPropertyValueSet*) const override;
  bool ValueIsPresentInStyle(HTMLElement*, CSSPropertyValueSet*) const override;

  void Trace(Visitor* visitor) const override {
    HTMLElementEquivalent::Trace(visitor);
  }
};

HTMLTextDecorationEquivalent::HTMLTextDecorationEquivalent(
    CSSValueID primitive_value,
    const HTMLQualifiedName& tag_name)
    : HTMLElementEquivalent(CSSPropertyID::kTextDecorationLine,
                            primitive_value,
                            tag_name)
// CSSPropertyID::kTextDecorationLine is used in
// HTMLElementEquivalent::AddToStyle
{}

bool HTMLTextDecorationEquivalent::PropertyExistsInStyle(
    const CSSPropertyValueSet* style) const {
  return style->GetPropertyCSSValue(
             CSSPropertyID::kWebkitTextDecorationsInEffect) ||
         style->GetPropertyCSSValue(CSSPropertyID::kTextDecorationLine);
}

bool HTMLTextDecorationEquivalent::ValueIsPresentInStyle(
    HTMLElement* element,
    CSSPropertyValueSet* style) const {
  const CSSValue* style_value =
      style->GetPropertyCSSValue(CSSPropertyID::kWebkitTextDecorationsInEffect);
  if (!style_value) {
    style_value =
        style->GetPropertyCSSValue(CSSPropertyID::kTextDecorationLine);
  }
  if (!Matches(element))
    return false;
  auto* style_value_list = DynamicTo<CSSValueList>(style_value);
  return style_value_list && style_value_list->HasValue(*identifier_value_);
}

class HTMLAttributeEquivalent : public HTMLElementEquivalent {
 public:
  HTMLAttributeEquivalent(CSSPropertyID,
                          const HTMLQualifiedName& tag_name,
                          const QualifiedName& attr_name);
  HTMLAttributeEquivalent(CSSPropertyID, const QualifiedName& attr_name);

  bool Matches(const Element* element) const override {
    return HTMLElementEquivalent::Matches(element) &&
           element->hasAttribute(attr_name_);
  }
  bool HasAttribute() const override { return true; }
  bool ValueIsPresentInStyle(HTMLElement*, CSSPropertyValueSet*) const override;
  void AddToStyle(Element*, EditingStyle*) const override;
  virtual const CSSValue* AttributeValueAsCSSValue(Element*) const;
  inline const QualifiedName& AttributeName() const { return attr_name_; }

  void Trace(Visitor* visitor) const override {
    HTMLElementEquivalent::Trace(visitor);
  }

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

HTMLAttributeEquivalent::HTMLAttributeEquivalent(
    CSSPropertyID id,
    const HTMLQualifiedName& tag_name,
    const QualifiedName& attr_name)
    : HTMLElementEquivalent(id, tag_name), attr_name_(attr_name) {}

HTMLAttributeEquivalent::HTMLAttributeEquivalent(CSSPropertyID id,
                                                 const QualifiedName& attr_name)
    : HTMLElementEquivalent(id), attr_name_(attr_name) {}

bool HTMLAttributeEquivalent::ValueIsPresentInStyle(
    HTMLElement* element,
    CSSPropertyValueSet* style) const {
  const CSSValue* value = AttributeValueAsCSSValue(element);
  const CSSValue* style_value = style->GetPropertyCSSValue(property_id_);

  return DataEquivalent(value, style_value);
}

void HTMLAttributeEquivalent::AddToStyle(Element* element,
                                         EditingStyle* style) const {
  if (const CSSValue* value = AttributeValueAsCSSValue(element)) {
    style->SetProperty(property_id_, value->CssText(), /* important */ false,
                       element->GetExecutionContext()->GetSecureContextMode());
  }
}

const CSSValue* HTMLAttributeEquivalent::AttributeValueAsCSSValue(
    Element* element) const {
  DCHECK(element);
  const AtomicString& value = element->getAttribute(attr_name_);
  if (value.IsNull())
    return nullptr;

  auto* dummy_style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  dummy_style->SetProperty(
      property_id_, value, /* important */ false,
      element->GetExecutionContext()->GetSecureContextMode());
  return dummy_style->GetPropertyCSSValue(property_id_);
}

class HTMLFontSizeEquivalent final : public HTMLAttributeEquivalent {
 public:
  static HTMLFontSizeEquivalent* Create() {
    return MakeGarbageCollected<HTMLFontSizeEquivalent>();
  }

  HTMLFontSizeEquivalent();

  const CSSValue* AttributeValueAsCSSValue(Element*) const override;

  void Trace(Visitor* visitor) const override {
    HTMLAttributeEquivalent::Trace(visitor);
  }
};

HTMLFontSizeEquivalent::HTMLFontSizeEquivalent()
    : HTMLAttributeEquivalent(CSSPropertyID::kFontSize,
                              html_names::kFontTag,
                              html_names::kSizeAttr) {}

const CSSValue* HTMLFontSizeEquivalent::AttributeValueAsCSSValue(
    Element* element) const {
  DCHECK(element);
  const AtomicString& value = element->getAttribute(attr_name_);
  if (value.IsNull())
    return nullptr;
  CSSValueID size;
  if (!HTMLFontElement::CssValueFromFontSizeNumber(value, size))
    return nullptr;
  return CSSIdentifierValue::Create(size);
}

EditingStyle::EditingStyle(ContainerNode* node,
                           PropertiesToInclude properties_to_include) {
  Init(node, properties_to_include);
}

EditingStyle::EditingStyle(const Position& position,
                           PropertiesToInclude properties_to_include) {
  Init(position.AnchorNode(), properties_to_include);
}

EditingStyle::EditingStyle(const CSSPropertyValueSet* style)
    : mutable_style_(style ? style->MutableCopy() : nullptr) {
  ExtractFontSizeDelta();
}

EditingStyle::EditingStyle(CSSPropertyID property_id,
                           const String& value,
                           SecureContextMode secure_context_mode)
    : mutable_style_(nullptr) {
  SetProperty(property_id, value, /* important */ false, secure_context_mode);
  is_vertical_align_ = property_id == CSSPropertyID::kVerticalAlign &&
                       (value == "sub" || value == "super");
}

static Color CssValueToColor(const CSSValue* value) {
  if (!value)
    return Color::kTransparent;

  auto* color_value = DynamicTo<cssvalue::CSSColorValue>(value);
  if (!color_value && !value->IsPrimitiveValue() && !value->IsIdentifierValue())
    return Color::kTransparent;

  if (color_value)
    return color_value->Value();

  Color color = 0;
  // FIXME: Why ignore the return value?
  CSSParser::ParseColor(color, value->CssText());
  return color;
}

static inline Color GetFontColor(CSSStyleDeclaration* style) {
  return CssValueToColor(
      style->GetPropertyCSSValueInternal(CSSPropertyID::kColor));
}

static inline Color GetFontColor(CSSPropertyValueSet* style) {
  return CssValueToColor(style->GetPropertyCSSValue(CSSPropertyID::kColor));
}

static inline Color GetBackgroundColor(CSSStyleDeclaration* style) {
  return CssValueToColor(
      style->GetPropertyCSSValueInternal(CSSPropertyID::kBackgroundColor));
}

static inline Color GetBackgroundColor(CSSPropertyValueSet* style) {
  return CssValueToColor(
      style->GetPropertyCSSValue(CSSPropertyID::kBackgroundColor));
}

static inline Color BackgroundColorInEffect(Node* node) {
  return CssValueToColor(
      EditingStyleUtilities::BackgroundColorValueInEffect(node));
}

static CSSValueID NormalizeTextAlign(CSSValueID text_align) {
  switch (text_align) {
    case CSSValueID::kCenter:
    case CSSValueID::kWebkitCenter:
      return CSSValueID::kCenter;
    case CSSValueID::kJustify:
      return CSSValueID::kJustify;
    case CSSValueID::kLeft:
    case CSSValueID::kWebkitLeft:
      return CSSValueID::kLeft;
    case CSSValueID::kRight:
    case CSSValueID::kWebkitRight:
      return CSSValueID::kRight;
    case CSSValueID::kStart:
    case CSSValueID::kEnd:
      return text_align;
    default:
      return CSSValueID::kInvalid;
  }
}
static CSSValueID TextAlignResolvingStartAndEnd(CSSValueID text_align,
                                                TextDirection direction) {
  const CSSValueID normalized = NormalizeTextAlign(text_align);
  switch (normalized) {
    case CSSValueID::kStart:
      return IsLtr(direction) ? CSSValueID::kLeft : CSSValueID::kRight;
    case CSSValueID::kEnd:
      return IsLtr(direction) ? CSSValueID::kRight : CSSValueID::kLeft;
    default:
      return normalized;
  }
}

// Returns true "text-align" property of |style| is redundant when applying
// |style| inheriting from |base_style| to |node|.
// Note: direction for "text-align:start" and "text-align:end" are taken
// from |node|.
template <typename T>
static bool IsRedundantTextAlign(MutableCSSPropertyValueSet* style,
                                 T* base_style,
                                 Node* node) {
  DCHECK(node);
  const CSSValueID base_text_align = NormalizeTextAlign(
      GetIdentifierValue(base_style, CSSPropertyID::kTextAlign));
  if (base_text_align == CSSValueID::kInvalid)
    return false;
  const CSSValueID text_align =
      NormalizeTextAlign(GetIdentifierValue(style, CSSPropertyID::kTextAlign));
  if (text_align == CSSValueID::kInvalid)
    return false;
  if (text_align == base_text_align)
    return true;
  if (base_text_align == CSSValueID::kStart ||
      base_text_align == CSSValueID::kEnd) {
    // Returns true for "text-align:left" of <p>
    //   <div style="text-align:start"><p dir="ltr" style="text-align:left">
    // because meaning of "text-align:start" in <p> is identical to
    // "text-align:left".
    //
    // Returns false for "text-align:left" of <p>
    //   <div style="text-align:start"><p dir="rtl" style="text-align:left">
    // because meaning of "text-align:start" in <p> is identical to
    // "text-align:right".
    return TextAlignResolvingStartAndEnd(
               base_text_align, node->EnsureComputedStyle()->Direction()) ==
           text_align;
  }
  if (text_align == CSSValueID::kStart || text_align == CSSValueID::kEnd) {
    // Returns true for "text-align:start" of <p>
    //  <div style="text-align:left"><p dir="ltr" style="text-align:start">
    //  <div style="text-align:right"><p dir="rtl" style="text-align:start">
    // Returns false for "text-align:start" of <p>
    //  <div style="text-align:left"><p dir="rtl" style="text-align:start">
    //  <div style="text-align:right"><p dir="ltr" style="text-align:start">
    return TextAlignResolvingStartAndEnd(
               text_align, node->EnsureComputedStyle()->Direction()) ==
           base_text_align;
  }
  return false;
}

void EditingStyle::Init(Node* node, PropertiesToInclude properties_to_include) {
  if (IsTabHTMLSpanElementTextNode(node))
    node = TabSpanElement(node)->parentNode();
  else if (IsTabHTMLSpanElement(node))
    node = node->parentNode();
  node_ = node;
  auto* computed_style_at_position =
      MakeGarbageCollected<CSSComputedStyleDeclaration>(node);
  mutable_style_ =
      properties_to_include == kAllProperties && computed_style_at_position
          ? computed_style_at_position->CopyProperties()
          : CopyEditingProperties(node ? node->GetExecutionContext() : nullptr,
                                  computed_style_at_position);

  if (properties_to_include == kEditingPropertiesInEffect) {
    if (const CSSValue* value =
            EditingStyleUtilities::BackgroundColorValueInEffect(node)) {
      mutable_style_->SetProperty(
          CSSPropertyID::kBackgroundColor, value->CssText(),
          /* important */ false,
          node->GetExecutionContext()->GetSecureContextMode());
    }
    if (const CSSValue* value = computed_style_at_position->GetPropertyCSSValue(
            CSSPropertyID::kWebkitTextDecorationsInEffect)) {
      mutable_style_->SetProperty(
          CSSPropertyID::kTextDecoration, value->CssText(),
          /* important */ false,
          node->GetExecutionContext()->GetSecureContextMode());
    }
  }

  if (node && node->EnsureComputedStyle()) {
    const ComputedStyle* computed_style = node->EnsureComputedStyle();

    // Fix for crbug.com/768261: due to text-autosizing, reading the current
    // computed font size and re-writing it to an element may actually cause the
    // font size to become larger (since the autosizer will run again on the new
    // computed size). The fix is to toss out the computed size property here
    // and use ComputedStyle::SpecifiedFontSize().
    if (computed_style->ComputedFontSize() !=
        computed_style->SpecifiedFontSize()) {
      // ReplaceSelectionCommandTest_TextAutosizingDoesntInflateText gets here.
      mutable_style_->SetProperty(
          CSSPropertyID::kFontSize,
          CSSNumericLiteralValue::Create(computed_style->SpecifiedFontSize(),
                                         CSSPrimitiveValue::UnitType::kPixels)
              ->CssText(),
          /* important */ false,
          node->GetExecutionContext()->GetSecureContextMode());
    }

    RemoveInheritedColorsIfNeeded(computed_style);
    ReplaceFontSizeByKeywordIfPossible(
        computed_style, node->GetExecutionContext()->GetSecureContextMode(),
        computed_style_at_position);
  }

  is_monospace_font_ = computed_style_at_position->IsMonospaceFont();
  ExtractFontSizeDelta();
}

void EditingStyle::RemoveInheritedColorsIfNeeded(
    const ComputedStyle* computed_style) {
  // If a node's text fill color is currentColor, then its children use
  // their font-color as their text fill color (they don't
  // inherit it).  Likewise for stroke color.
  // Similar thing happens for caret-color if it's auto or currentColor.
  if (computed_style->TextFillColor().IsCurrentColor())
    mutable_style_->RemoveProperty(CSSPropertyID::kWebkitTextFillColor);
  if (computed_style->TextStrokeColor().IsCurrentColor())
    mutable_style_->RemoveProperty(CSSPropertyID::kWebkitTextStrokeColor);
  if (computed_style->CaretColor().IsAutoColor() ||
      computed_style->CaretColor().IsCurrentColor())
    mutable_style_->RemoveProperty(CSSPropertyID::kCaretColor);
}

CSSValueID EditingStyle::GetProperty(CSSPropertyID property_id) const {
  return GetIdentifierValue(mutable_style_.Get(), property_id);
}

void EditingStyle::SetProperty(CSSPropertyID property_id,
                               const String& value,
                               bool important,
                               SecureContextMode secure_context_mode) {
  if (!mutable_style_) {
    mutable_style_ =
        MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  }

  mutable_style_->SetProperty(property_id, value, important,
                              secure_context_mode);
}

void EditingStyle::ReplaceFontSizeByKeywordIfPossible(
    const ComputedStyle* computed_style,
    SecureContextMode secure_context_mode,
    CSSComputedStyleDeclaration* css_computed_style) {
  DCHECK(computed_style);
  if (computed_style->GetFontDescription().KeywordSize()) {
    mutable_style_->SetProperty(
        CSSPropertyID::kFontSize,
        css_computed_style->GetFontSizeCSSValuePreferringKeyword()->CssText(),
        /* important */ false, secure_context_mode);
  }
}

void EditingStyle::ExtractFontSizeDelta() {
  if (!mutable_style_)
    return;

  if (mutable_style_->GetPropertyCSSValue(CSSPropertyID::kFontSize)) {
    // Explicit font size overrides any delta.
    mutable_style_->RemoveProperty(CSSPropertyID::kInternalFontSizeDelta);
    return;
  }

  // Get the adjustment amount out of the style.
  const CSSValue* value = mutable_style_->GetPropertyCSSValue(
      CSSPropertyID::kInternalFontSizeDelta);
  const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value);
  if (!primitive_value)
    return;

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

  font_size_delta_ = primitive_value->GetFloatValue();
  mutable_style_->RemoveProperty(CSSPropertyID::kInternalFontSizeDelta);
}

bool EditingStyle::IsEmpty() const {
  return (!mutable_style_ || mutable_style_->IsEmpty()) &&
         font_size_delta_ == kNoFontDelta;
}

bool EditingStyle::GetTextDirection(
    mojo_base::mojom::blink::TextDirection& writing_direction) const {
  if (!mutable_style_)
    return false;

  const CSSValue* unicode_bidi =
      mutable_style_->GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi);
  auto* unicode_bidi_identifier_value =
      DynamicTo<CSSIdentifierValue>(unicode_bidi);
  if (!unicode_bidi_identifier_value)
    return false;

  CSSValueID unicode_bidi_value = unicode_bidi_identifier_value->GetValueID();
  if (EditingStyleUtilities::IsEmbedOrIsolate(unicode_bidi_value)) {
    const CSSValue* direction =
        mutable_style_->GetPropertyCSSValue(CSSPropertyID::kDirection);
    auto* direction_identifier_value = DynamicTo<CSSIdentifierValue>(direction);
    if (!direction_identifier_value)
      return false;

    writing_direction =
        direction_identifier_value->GetValueID() == CSSValueID::kLtr
            ? mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT
            : mojo_base::mojom::blink::TextDirection::RIGHT_TO_LEFT;

    return true;
  }

  if (unicode_bidi_value == CSSValueID::kNormal) {
    writing_direction =
        mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;
    return true;
  }

  return false;
}

void EditingStyle::OverrideWithStyle(const CSSPropertyValueSet* style) {
  if (!style || style->IsEmpty())
    return;
  if (!mutable_style_) {
    mutable_style_ =
        MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  }
  mutable_style_->MergeAndOverrideOnConflict(style);
  ExtractFontSizeDelta();
}

void EditingStyle::Clear() {
  mutable_style_.Clear();
  is_monospace_font_ = false;
  font_size_delta_ = kNoFontDelta;
}

EditingStyle* EditingStyle::Copy() const {
  EditingStyle* copy = MakeGarbageCollected<EditingStyle>();
  if (mutable_style_)
    copy->mutable_style_ = mutable_style_->MutableCopy();
  copy->is_monospace_font_ = is_monospace_font_;
  copy->font_size_delta_ = font_size_delta_;
  return copy;
}

// This is the list of CSS properties that apply specially to block-level
// elements.
static const CSSPropertyID kStaticBlockProperties[] = {
    CSSPropertyID::kBreakAfter, CSSPropertyID::kBreakBefore,
    CSSPropertyID::kBreakInside, CSSPropertyID::kOrphans,
    CSSPropertyID::kOverflow,  // This can be also be applied to replaced
                               // elements
    CSSPropertyID::kColumnCount, CSSPropertyID::kColumnGap,
    CSSPropertyID::kColumnRuleColor, CSSPropertyID::kColumnRuleStyle,
    CSSPropertyID::kColumnRuleWidth, CSSPropertyID::kWebkitColumnBreakBefore,
    CSSPropertyID::kWebkitColumnBreakAfter,
    CSSPropertyID::kWebkitColumnBreakInside, CSSPropertyID::kColumnWidth,
    CSSPropertyID::kPageBreakAfter, CSSPropertyID::kPageBreakBefore,
    CSSPropertyID::kPageBreakInside, CSSPropertyID::kTextAlign,
    CSSPropertyID::kTextAlignLast, CSSPropertyID::kTextIndent,
    CSSPropertyID::kTextJustify, CSSPropertyID::kWidows};

static const Vector<const CSSProperty*>& BlockPropertiesVector(
    const ExecutionContext* execution_context) {
  DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ());
  if (properties.IsEmpty()) {
    CSSProperty::FilterWebExposedCSSPropertiesIntoVector(
        execution_context, kStaticBlockProperties,
        base::size(kStaticBlockProperties), properties);
  }
  return properties;
}

EditingStyle* EditingStyle::ExtractAndRemoveBlockProperties(
    const ExecutionContext* execution_context) {
  EditingStyle* block_properties = MakeGarbageCollected<EditingStyle>();
  if (!mutable_style_)
    return block_properties;

  block_properties->mutable_style_ = mutable_style_->CopyPropertiesInSet(
      BlockPropertiesVector(execution_context));
  RemoveBlockProperties(execution_context);

  return block_properties;
}

EditingStyle* EditingStyle::ExtractAndRemoveTextDirection(
    SecureContextMode secure_context_mode) {
  EditingStyle* text_direction = MakeGarbageCollected<EditingStyle>();
  text_direction->mutable_style_ =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  text_direction->mutable_style_->SetProperty(
      CSSPropertyID::kUnicodeBidi, CSSValueID::kIsolate,
      mutable_style_->PropertyIsImportant(CSSPropertyID::kUnicodeBidi));

  text_direction->mutable_style_->SetProperty(
      CSSPropertyID::kDirection,
      mutable_style_->GetPropertyValue(CSSPropertyID::kDirection),
      mutable_style_->PropertyIsImportant(CSSPropertyID::kDirection),
      secure_context_mode);

  mutable_style_->RemoveProperty(CSSPropertyID::kUnicodeBidi);
  mutable_style_->RemoveProperty(CSSPropertyID::kDirection);

  return text_direction;
}

void EditingStyle::RemoveBlockProperties(
    const ExecutionContext* execution_context) {
  if (!mutable_style_)
    return;

  mutable_style_->RemovePropertiesInSet(
      BlockPropertiesVector(execution_context).data(),
      BlockPropertiesVector(execution_context).size());
}

void EditingStyle::RemoveStyleAddedByElement(Element* element) {
  if (!element || !element->parentNode())
    return;
  MutableCSSPropertyValueSet* parent_style = CopyEditingProperties(
      element->parentNode()->GetExecutionContext(),
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()),
      kAllEditingProperties);
  MutableCSSPropertyValueSet* node_style = CopyEditingProperties(
      element->GetExecutionContext(),
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element),
      kAllEditingProperties);
  node_style->RemoveEquivalentProperties(parent_style);
  mutable_style_->RemoveEquivalentProperties(node_style);
}

void EditingStyle::RemoveStyleConflictingWithStyleOfElement(Element* element) {
  if (!element || !element->parentNode() || !mutable_style_)
    return;

  MutableCSSPropertyValueSet* parent_style = CopyEditingProperties(
      element->parentNode()->GetExecutionContext(),
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()),
      kAllEditingProperties);
  MutableCSSPropertyValueSet* node_style = CopyEditingProperties(
      element->GetExecutionContext(),
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element),
      kAllEditingProperties);
  node_style->RemoveEquivalentProperties(parent_style);

  unsigned property_count = node_style->PropertyCount();
  for (unsigned i = 0; i < property_count; ++i)
    mutable_style_->RemoveProperty(node_style->PropertyAt(i).Id());
}

void EditingStyle::CollapseTextDecorationProperties(
    SecureContextMode secure_context_mode) {
  if (!mutable_style_)
    return;

  const CSSValue* text_decorations_in_effect =
      mutable_style_->GetPropertyCSSValue(
          CSSPropertyID::kWebkitTextDecorationsInEffect);
  if (!text_decorations_in_effect)
    return;

  if (text_decorations_in_effect->IsValueList()) {
    mutable_style_->SetProperty(
        CSSPropertyID::kTextDecorationLine,
        text_decorations_in_effect->CssText(),
        mutable_style_->PropertyIsImportant(CSSPropertyID::kTextDecorationLine),
        secure_context_mode);
  } else {
    mutable_style_->RemoveProperty(CSSPropertyID::kTextDecorationLine);
  }
  mutable_style_->RemoveProperty(CSSPropertyID::kWebkitTextDecorationsInEffect);
}

EditingTriState EditingStyle::TriStateOfStyle(
    ExecutionContext* execution_context,
    EditingStyle* style,
    SecureContextMode secure_context_mode) const {
  if (!style || !style->mutable_style_)
    return EditingTriState::kFalse;
  DCHECK(style->node_);
  return TriStateOfStyle(
      style->mutable_style_->EnsureCSSStyleDeclaration(execution_context),
      style->node_, kDoNotIgnoreTextOnlyProperties, secure_context_mode);
}

EditingTriState EditingStyle::TriStateOfStyle(
    CSSStyleDeclaration* style_to_compare,
    Node* node,
    ShouldIgnoreTextOnlyProperties should_ignore_text_only_properties,
    SecureContextMode secure_context_mode) const {
  // editing/execCommand/query-text-alignment.html requires |node|.
  DCHECK(node);
  MutableCSSPropertyValueSet* difference = GetPropertiesNotIn(
      mutable_style_.Get(), node, style_to_compare, secure_context_mode);

  // CSS properties that create a visual difference only when applied to text.
  static const CSSProperty* kTextOnlyProperties[] = {
      // FIXME: CSSPropertyID::kTextDecoration needs to be removed when CSS3
      // Text
      // Decoration feature is no longer experimental.
      &GetCSSPropertyTextDecoration(),
      &GetCSSPropertyTextDecorationLine(),
      &GetCSSPropertyWebkitTextDecorationsInEffect(),
      &GetCSSPropertyFontStyle(),
      &GetCSSPropertyFontWeight(),
      &GetCSSPropertyColor(),
  };
  if (should_ignore_text_only_properties == kIgnoreTextOnlyProperties) {
    difference->RemovePropertiesInSet(kTextOnlyProperties,
                                      base::size(kTextOnlyProperties));
  }

  if (difference->IsEmpty())
    return EditingTriState::kTrue;
  if (difference->PropertyCount() == mutable_style_->PropertyCount())
    return EditingTriState::kFalse;

  return EditingTriState::kMixed;
}

EditingTriState EditingStyle::TriStateOfStyle(
    const VisibleSelection& selection,
    SecureContextMode secure_context_mode) const {
  if (selection.IsNone())
    return EditingTriState::kFalse;

  if (selection.IsCaret()) {
    return TriStateOfStyle(
        selection.Start().AnchorNode()->GetExecutionContext(),
        EditingStyleUtilities::CreateStyleAtSelectionStart(selection),
        secure_context_mode);
  }

  EditingTriState state = EditingTriState::kFalse;
  bool node_is_start = true;
  for (Node& node : NodeTraversal::StartsAt(*selection.Start().AnchorNode())) {
    if (node.GetLayoutObject() && HasEditableStyle(node)) {
      auto* node_style =
          MakeGarbageCollected<CSSComputedStyleDeclaration>(&node);
      if (node_style) {
        // If the selected element has <sub> or <sup> ancestor element, apply
        // the corresponding style(vertical-align) to it so that
        // document.queryCommandState() works with the style. See bug
        // http://crbug.com/582225.
        if (is_vertical_align_ &&
            GetIdentifierValue(node_style, CSSPropertyID::kVerticalAlign) ==
                CSSValueID::kBaseline) {
          const auto* vertical_align =
              To<CSSIdentifierValue>(mutable_style_->GetPropertyCSSValue(
                  CSSPropertyID::kVerticalAlign));
          if (EditingStyleUtilities::HasAncestorVerticalAlignStyle(
                  node, vertical_align->GetValueID())) {
            node.MutableComputedStyleForEditingDeprecated()->SetVerticalAlign(
                vertical_align->ConvertTo<EVerticalAlign>());
          }
        }

        // Pass EditingStyle::DoNotIgnoreTextOnlyProperties without checking if
        // node.isTextNode() because the node can be an element node. See bug
        // http://crbug.com/584939.
        EditingTriState node_state = TriStateOfStyle(
            node_style, &node, EditingStyle::kDoNotIgnoreTextOnlyProperties,
            secure_context_mode);
        if (node_is_start) {
          state = node_state;
          node_is_start = false;
        } else if (state != node_state && node.IsTextNode()) {
          state = EditingTriState::kMixed;
          break;
        }
      }
    }
    if (&node == selection.End().AnchorNode())
      break;
  }

  return state;
}

bool EditingStyle::ConflictsWithInlineStyleOfElement(
    HTMLElement* element,
    EditingStyle* extracted_style,
    Vector<CSSPropertyID>* conflicting_properties) const {
  DCHECK(element);
  DCHECK(!conflicting_properties || conflicting_properties->IsEmpty());

  const CSSPropertyValueSet* inline_style = element->InlineStyle();
  if (!mutable_style_ || !inline_style)
    return false;

  unsigned property_count = mutable_style_->PropertyCount();
  for (unsigned i = 0; i < property_count; ++i) {
    CSSPropertyID property_id = mutable_style_->PropertyAt(i).Id();

    // We don't override whitespace property of a tab span because that would
    // collapse the tab into a space.
    if (property_id == CSSPropertyID::kWhiteSpace &&
        IsTabHTMLSpanElement(element))
      continue;

    if (property_id == CSSPropertyID::kWebkitTextDecorationsInEffect &&
        inline_style->GetPropertyCSSValue(CSSPropertyID::kTextDecorationLine)) {
      if (!conflicting_properties)
        return true;
      conflicting_properties->push_back(CSSPropertyID::kTextDecoration);
      // Because text-decoration expands to text-decoration-line,
      // we also state it as conflicting.
      conflicting_properties->push_back(CSSPropertyID::kTextDecorationLine);
      if (extracted_style) {
        extracted_style->SetProperty(
            CSSPropertyID::kTextDecorationLine,
            inline_style->GetPropertyValue(CSSPropertyID::kTextDecorationLine),
            inline_style->PropertyIsImportant(
                CSSPropertyID::kTextDecorationLine),
            element->GetExecutionContext()->GetSecureContextMode());
      }
      continue;
    }

    if (!inline_style->GetPropertyCSSValue(property_id))
      continue;

    if (property_id == CSSPropertyID::kUnicodeBidi &&
        inline_style->GetPropertyCSSValue(CSSPropertyID::kDirection)) {
      if (!conflicting_properties)
        return true;
      conflicting_properties->push_back(CSSPropertyID::kDirection);
      if (extracted_style) {
        extracted_style->SetProperty(
            property_id, inline_style->GetPropertyValue(property_id),
            inline_style->PropertyIsImportant(property_id),
            element->GetExecutionContext()->GetSecureContextMode());
      }
    }

    if (!conflicting_properties)
      return true;

    conflicting_properties->push_back(property_id);

    if (extracted_style) {
      extracted_style->SetProperty(
          property_id, inline_style->GetPropertyValue(property_id),
          inline_style->PropertyIsImportant(property_id),
          element->GetExecutionContext()->GetSecureContextMode());
    }
  }

  return conflicting_properties && !conflicting_properties->IsEmpty();
}

static const HeapVector<Member<HTMLElementEquivalent>>&
HtmlElementEquivalents() {
  DEFINE_STATIC_LOCAL(
      Persistent<HeapVector<Member<HTMLElementEquivalent>>>,
      html_element_equivalents,
      (MakeGarbageCollected<HeapVector<Member<HTMLElementEquivalent>>>()));
  if (!html_element_equivalents->size()) {
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(
            CSSPropertyID::kFontWeight, CSSValueID::kBold, html_names::kBTag));
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(CSSPropertyID::kFontWeight,
                                                    CSSValueID::kBold,
                                                    html_names::kStrongTag));
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(
            CSSPropertyID::kVerticalAlign, CSSValueID::kSub,
            html_names::kSubTag));
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(
            CSSPropertyID::kVerticalAlign, CSSValueID::kSuper,
            html_names::kSupTag));
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(
            CSSPropertyID::kFontStyle, CSSValueID::kItalic, html_names::kITag));
    html_element_equivalents->push_back(
        MakeGarbageCollected<HTMLElementEquivalent>(CSSPropertyID::kFontStyle,
                                                    CSSValueID::kItalic,
                                                    html_names::kEmTag));

    html_element_equivalents->push_back(HTMLTextDecorationEquivalent::Create(
        CSSValueID::kUnderline, html_names::kUTag));
    html_element_equivalents->push_back(HTMLTextDecorationEquivalent::Create(
        CSSValueID::kLineThrough, html_names::kSTag));
    html_element_equivalents->push_back(HTMLTextDecorationEquivalent::Create(
        CSSValueID::kLineThrough, html_names::kStrikeTag));
  }

  return *html_element_equivalents;
}

bool EditingStyle::ConflictsWithImplicitStyleOfElement(
    HTMLElement* element,
    EditingStyle* extracted_style,
    ShouldExtractMatchingStyle should_extract_matching_style) const {
  if (!mutable_style_)
    return false;

  const HeapVector<Member<HTMLElementEquivalent>>& html_element_equivalents =
      HtmlElementEquivalents();
  for (wtf_size_t i = 0; i < html_element_equivalents.size(); ++i) {
    const HTMLElementEquivalent* equivalent = html_element_equivalents[i].Get();
    if (equivalent->Matches(element) &&
        equivalent->PropertyExistsInStyle(mutable_style_.Get()) &&
        (should_extract_matching_style == kExtractMatchingStyle ||
         !equivalent->ValueIsPresentInStyle(element, mutable_style_.Get()))) {
      if (extracted_style)
        equivalent->AddToStyle(element, extracted_style);
      return true;
    }
  }
  return false;
}

static const HeapVector<Member<HTMLAttributeEquivalent>>&
HtmlAttributeEquivalents() {
  DEFINE_STATIC_LOCAL(
      Persistent<HeapVector<Member<HTMLAttributeEquivalent>>>,
      html_attribute_equivalents,
      (MakeGarbageCollected<HeapVector<Member<HTMLAttributeEquivalent>>>()));
  if (!html_attribute_equivalents->size()) {
    // elementIsStyledSpanOrHTMLEquivalent depends on the fact each
    // HTMLAttriuteEquivalent matches exactly one attribute of exactly one
    // element except dirAttr.
    html_attribute_equivalents->push_back(
        MakeGarbageCollected<HTMLAttributeEquivalent>(CSSPropertyID::kColor,
                                                      html_names::kFontTag,
                                                      html_names::kColorAttr));
    html_attribute_equivalents->push_back(
        MakeGarbageCollected<HTMLAttributeEquivalent>(
            CSSPropertyID::kFontFamily, html_names::kFontTag,
            html_names::kFaceAttr));
    html_attribute_equivalents->push_back(HTMLFontSizeEquivalent::Create());

    html_attribute_equivalents->push_back(
        MakeGarbageCollected<HTMLAttributeEquivalent>(CSSPropertyID::kDirection,
                                                      html_names::kDirAttr));
    html_attribute_equivalents->push_back(
        MakeGarbageCollected<HTMLAttributeEquivalent>(
            CSSPropertyID::kUnicodeBidi, html_names::kDirAttr));
  }

  return *html_attribute_equivalents;
}

bool EditingStyle::ConflictsWithImplicitStyleOfAttributes(
    HTMLElement* element) const {
  DCHECK(element);
  if (!mutable_style_)
    return false;

  const HeapVector<Member<HTMLAttributeEquivalent>>&
      html_attribute_equivalents = HtmlAttributeEquivalents();
  for (const auto& equivalent : html_attribute_equivalents) {
    if (equivalent->Matches(element) &&
        equivalent->PropertyExistsInStyle(mutable_style_.Get()) &&
        !equivalent->ValueIsPresentInStyle(element, mutable_style_.Get()))
      return true;
  }

  return false;
}

bool EditingStyle::ExtractConflictingImplicitStyleOfAttributes(
    HTMLElement* element,
    ShouldPreserveWritingDirection should_preserve_writing_direction,
    EditingStyle* extracted_style,
    Vector<QualifiedName>& conflicting_attributes,
    ShouldExtractMatchingStyle should_extract_matching_style) const {
  DCHECK(element);
  // HTMLAttributeEquivalent::addToStyle doesn't support unicode-bidi and
  // direction properties
  if (extracted_style)
    DCHECK_EQ(should_preserve_writing_direction, kPreserveWritingDirection);
  if (!mutable_style_)
    return false;

  const HeapVector<Member<HTMLAttributeEquivalent>>&
      html_attribute_equivalents = HtmlAttributeEquivalents();
  bool removed = false;
  for (const auto& attribute : html_attribute_equivalents) {
    const HTMLAttributeEquivalent* equivalent = attribute.Get();

    // unicode-bidi and direction are pushed down separately so don't push down
    // with other styles.
    if (should_preserve_writing_direction == kPreserveWritingDirection &&
        equivalent->AttributeName() == html_names::kDirAttr)
      continue;

    if (!equivalent->Matches(element) ||
        !equivalent->PropertyExistsInStyle(mutable_style_.Get()) ||
        (should_extract_matching_style == kDoNotExtractMatchingStyle &&
         equivalent->ValueIsPresentInStyle(element, mutable_style_.Get())))
      continue;

    if (extracted_style)
      equivalent->AddToStyle(element, extracted_style);
    conflicting_attributes.push_back(equivalent->AttributeName());
    removed = true;
  }

  return removed;
}

bool EditingStyle::StyleIsPresentInComputedStyleOfNode(Node* node) const {
  return !mutable_style_ ||
         GetPropertiesNotIn(
             mutable_style_.Get(), node,
             MakeGarbageCollected<CSSComputedStyleDeclaration>(node),
             node->GetExecutionContext()->GetSecureContextMode())
             ->IsEmpty();
}

bool EditingStyle::ElementIsStyledSpanOrHTMLEquivalent(
    const HTMLElement* element) {
  DCHECK(element);
  bool element_is_span_or_element_equivalent = false;
  if (IsA<HTMLSpanElement>(*element)) {
    element_is_span_or_element_equivalent = true;
  } else {
    const HeapVector<Member<HTMLElementEquivalent>>& html_element_equivalents =
        HtmlElementEquivalents();
    wtf_size_t i;
    for (i = 0; i < html_element_equivalents.size(); ++i) {
      if (html_element_equivalents[i]->Matches(element)) {
        element_is_span_or_element_equivalent = true;
        break;
      }
    }
  }

  AttributeCollection attributes = element->Attributes();
  if (attributes.IsEmpty()) {
    // span, b, etc... without any attributes
    return element_is_span_or_element_equivalent;
  }

  unsigned matched_attributes = 0;
  const HeapVector<Member<HTMLAttributeEquivalent>>&
      html_attribute_equivalents = HtmlAttributeEquivalents();
  for (const auto& equivalent : html_attribute_equivalents) {
    if (equivalent->Matches(element) &&
        equivalent->AttributeName() != html_names::kDirAttr)
      matched_attributes++;
  }

  if (!element_is_span_or_element_equivalent && !matched_attributes) {
    // element is not a span, a html element equivalent, or font element.
    return false;
  }

  if (element->hasAttribute(html_names::kStyleAttr)) {
    if (const CSSPropertyValueSet* style = element->InlineStyle()) {
      unsigned property_count = style->PropertyCount();
      for (unsigned i = 0; i < property_count; ++i) {
        if (!IsEditingProperty(element->GetExecutionContext(),
                               style->PropertyAt(i).Id()))
          return false;
      }
    }
    matched_attributes++;
  }

  // font with color attribute, span with style attribute, etc...
  DCHECK_LE(matched_attributes, attributes.size());
  return matched_attributes >= attributes.size();
}

void EditingStyle::PrepareToApplyAt(
    const Position& position,
    ShouldPreserveWritingDirection should_preserve_writing_direction) {
  if (!mutable_style_)
    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.
  EditingStyle* editing_style_at_position =
      MakeGarbageCollected<EditingStyle>(position, kEditingPropertiesInEffect);
  CSSPropertyValueSet* style_at_position =
      editing_style_at_position->mutable_style_.Get();

  const CSSValue* unicode_bidi = nullptr;
  const CSSValue* direction = nullptr;
  if (should_preserve_writing_direction == kPreserveWritingDirection) {
    unicode_bidi =
        mutable_style_->GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi);
    direction = mutable_style_->GetPropertyCSSValue(CSSPropertyID::kDirection);
  }

  mutable_style_->RemoveEquivalentProperties(style_at_position);

  DCHECK(editing_style_at_position->node_);
  if (IsRedundantTextAlign(mutable_style_.Get(), style_at_position,
                           editing_style_at_position->node_))
    mutable_style_->RemoveProperty(CSSPropertyID::kTextAlign);

  if (GetFontColor(mutable_style_.Get()) == GetFontColor(style_at_position))
    mutable_style_->RemoveProperty(CSSPropertyID::kColor);

  if (EditingStyleUtilities::HasTransparentBackgroundColor(
          mutable_style_.Get()) ||
      CssValueToColor(mutable_style_->GetPropertyCSSValue(
          CSSPropertyID::kBackgroundColor)) ==
          BackgroundColorInEffect(position.ComputeContainerNode()))
    mutable_style_->RemoveProperty(CSSPropertyID::kBackgroundColor);

  if (auto* unicode_bidi_identifier_value =
          DynamicTo<CSSIdentifierValue>(unicode_bidi)) {
    mutable_style_->SetProperty(CSSPropertyID::kUnicodeBidi,
                                unicode_bidi_identifier_value->GetValueID());
    if (auto* direction_identifier_value =
            DynamicTo<CSSIdentifierValue>(direction)) {
      mutable_style_->SetProperty(CSSPropertyID::kDirection,
                                  direction_identifier_value->GetValueID());
    }
  }
}

void EditingStyle::MergeTypingStyle(Document* document) {
  DCHECK(document);

  EditingStyle* typing_style = document->GetFrame()->GetEditor().TypingStyle();
  if (!typing_style || typing_style == this)
    return;

  MergeStyle(typing_style->Style(), kOverrideValues);
}

void EditingStyle::MergeInlineStyleOfElement(
    HTMLElement* element,
    CSSPropertyOverrideMode mode,
    PropertiesToInclude properties_to_include) {
  DCHECK(element);
  if (!element->InlineStyle())
    return;

  switch (properties_to_include) {
    case kAllProperties:
      MergeStyle(element->InlineStyle(), mode);
      return;
    case kOnlyEditingInheritableProperties:
      MergeStyle(CopyEditingProperties(element->GetExecutionContext(),
                                       element->InlineStyle(),
                                       kOnlyInheritableEditingProperties),
                 mode);
      return;
    case kEditingPropertiesInEffect:
      MergeStyle(
          CopyEditingProperties(element->GetExecutionContext(),
                                element->InlineStyle(), kAllEditingProperties),
          mode);
      return;
  }
}

static inline bool ElementMatchesAndPropertyIsNotInInlineStyleDecl(
    const HTMLElementEquivalent* equivalent,
    const Element* element,
    EditingStyle::CSSPropertyOverrideMode mode,
    CSSPropertyValueSet* style) {
  return equivalent->Matches(element) &&
         (!element->InlineStyle() ||
          !equivalent->PropertyExistsInStyle(element->InlineStyle())) &&
         (mode == EditingStyle::kOverrideValues ||
          !equivalent->PropertyExistsInStyle(style));
}

static MutableCSSPropertyValueSet* ExtractEditingProperties(
    const ExecutionContext* execution_context,
    const CSSPropertyValueSet* style,
    EditingStyle::PropertiesToInclude properties_to_include) {
  if (!style)
    return nullptr;

  switch (properties_to_include) {
    case EditingStyle::kAllProperties:
    case EditingStyle::kEditingPropertiesInEffect:
      return CopyEditingProperties(execution_context, style,
                                   kAllEditingProperties);
    case EditingStyle::kOnlyEditingInheritableProperties:
      return CopyEditingProperties(execution_context, style,
                                   kOnlyInheritableEditingProperties);
  }

  NOTREACHED();
  return nullptr;
}

void EditingStyle::MergeInlineAndImplicitStyleOfElement(
    Element* element,
    CSSPropertyOverrideMode mode,
    PropertiesToInclude properties_to_include) {
  EditingStyle* style_from_rules = MakeGarbageCollected<EditingStyle>();
  style_from_rules->MergeStyleFromRulesForSerialization(element);

  if (element->InlineStyle())
    style_from_rules->mutable_style_->MergeAndOverrideOnConflict(
        element->InlineStyle());

  style_from_rules->mutable_style_ = ExtractEditingProperties(
      element->GetExecutionContext(), style_from_rules->mutable_style_.Get(),
      properties_to_include);
  MergeStyle(style_from_rules->mutable_style_.Get(), mode);

  const HeapVector<Member<HTMLElementEquivalent>>& element_equivalents =
      HtmlElementEquivalents();
  for (const auto& equivalent : element_equivalents) {
    if (ElementMatchesAndPropertyIsNotInInlineStyleDecl(
            equivalent.Get(), element, mode, mutable_style_.Get()))
      equivalent->AddToStyle(element, this);
  }

  const HeapVector<Member<HTMLAttributeEquivalent>>& attribute_equivalents =
      HtmlAttributeEquivalents();
  for (const auto& attribute : attribute_equivalents) {
    if (attribute->AttributeName() == html_names::kDirAttr)
      continue;  // We don't want to include directionality
    if (ElementMatchesAndPropertyIsNotInInlineStyleDecl(
            attribute.Get(), element, mode, mutable_style_.Get()))
      attribute->AddToStyle(element, this);
  }
}

static const CSSValueList& MergeTextDecorationValues(
    const CSSValueList& merged_value,
    const CSSValueList& value_to_merge) {
  DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, underline,
                      (CSSIdentifierValue::Create(CSSValueID::kUnderline)));
  DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, line_through,
                      (CSSIdentifierValue::Create(CSSValueID::kLineThrough)));
  CSSValueList& result = *merged_value.Copy();
  if (value_to_merge.HasValue(*underline) && !merged_value.HasValue(*underline))
    result.Append(*underline);

  if (value_to_merge.HasValue(*line_through) &&
      !merged_value.HasValue(*line_through))
    result.Append(*line_through);

  return result;
}

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

  if (!mutable_style_) {
    mutable_style_ = style->MutableCopy();
    return;
  }

  unsigned property_count = style->PropertyCount();
  for (unsigned i = 0; i < property_count; ++i) {
    CSSPropertyValueSet::PropertyReference property = style->PropertyAt(i);
    const CSSValue* value = mutable_style_->GetPropertyCSSValue(property.Id());

    // text decorations never override values
    const auto* property_value_list = DynamicTo<CSSValueList>(property.Value());
    if ((property.Id() == CSSPropertyID::kTextDecorationLine ||
         property.Id() == CSSPropertyID::kWebkitTextDecorationsInEffect) &&
        property_value_list && value) {
      if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
        const CSSValueList& result =
            MergeTextDecorationValues(*value_list, *property_value_list);
        mutable_style_->SetProperty(property.Id(), result,
                                    property.IsImportant());
        continue;
      }
      // text-decoration: none is equivalent to not having the property
      value = nullptr;
    }

    if (mode == kOverrideValues || (mode == kDoNotOverrideValues && !value)) {
      mutable_style_->SetProperty(
          CSSPropertyValue(property.PropertyMetadata(), property.Value()));
    }
  }
}

static MutableCSSPropertyValueSet* StyleFromMatchedRulesForElement(
    Element* element,
    unsigned rules_to_include) {
  auto* style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  StyleRuleList* matched_rules =
      element->GetDocument().GetStyleResolver().StyleRulesForElement(
          element, rules_to_include);
  if (matched_rules) {
    for (unsigned i = 0; i < matched_rules->size(); ++i)
      style->MergeAndOverrideOnConflict(&matched_rules->at(i)->Properties());
  }
  return style;
}

void EditingStyle::MergeStyleFromRules(Element* element) {
  MutableCSSPropertyValueSet* style_from_matched_rules =
      StyleFromMatchedRulesForElement(
          element,
          StyleResolver::kAuthorCSSRules | StyleResolver::kCrossOriginCSSRules);
  // Styles from the inline style declaration, held in the variable "style",
  // take precedence over those from matched rules.
  if (mutable_style_)
    style_from_matched_rules->MergeAndOverrideOnConflict(mutable_style_.Get());

  Clear();
  mutable_style_ = style_from_matched_rules;
}

void EditingStyle::MergeStyleFromRulesForSerialization(Element* element) {
  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* computed_style_for_element =
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element);
  auto* from_computed_style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  {
    unsigned property_count = mutable_style_->PropertyCount();
    for (unsigned i = 0; i < property_count; ++i) {
      CSSPropertyValueSet::PropertyReference property =
          mutable_style_->PropertyAt(i);
      const CSSValue& value = property.Value();
      const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value);
      if (!primitive_value)
        continue;
      if (primitive_value->IsPercentage()) {
        CSSPropertyName name = property.Name();
        if (const CSSValue* computed_property_value =
                computed_style_for_element->GetPropertyCSSValue(name)) {
          from_computed_style->AddRespectingCascade(
              CSSPropertyValue(name, *computed_property_value));
        }
      }
    }
  }
  mutable_style_->MergeAndOverrideOnConflict(from_computed_style);
}

static void RemovePropertiesInStyle(
    MutableCSSPropertyValueSet* style_to_remove_properties_from,
    CSSPropertyValueSet* style) {
  unsigned property_count = style->PropertyCount();
  Vector<const CSSProperty*> properties_to_remove(property_count);
  for (unsigned i = 0; i < property_count; ++i) {
    // TODO(crbug.com/980160): Remove access to static Variable instance.
    properties_to_remove[i] = &CSSProperty::Get(style->PropertyAt(i).Id());
  }

  style_to_remove_properties_from->RemovePropertiesInSet(
      properties_to_remove.data(), properties_to_remove.size());
}

void EditingStyle::RemoveStyleFromRulesAndContext(Element* element,
                                                  ContainerNode* context) {
  DCHECK(element);
  if (!mutable_style_)
    return;

  // StyleResolver requires clean style.
  DCHECK_GE(element->GetDocument().Lifecycle().GetState(),
            DocumentLifecycle::kStyleClean);
  DCHECK(element->GetDocument().IsActive());

  SecureContextMode secure_context_mode =
      element->GetExecutionContext()->GetSecureContextMode();

  // 1. Remove style from matched rules because style remain without repeating
  // it in inline style declaration
  MutableCSSPropertyValueSet* style_from_matched_rules =
      StyleFromMatchedRulesForElement(element,
                                      StyleResolver::kAllButEmptyCSSRules);
  if (style_from_matched_rules && !style_from_matched_rules->IsEmpty()) {
    mutable_style_ =
        GetPropertiesNotIn(mutable_style_.Get(), element,
                           style_from_matched_rules->EnsureCSSStyleDeclaration(
                               element->GetExecutionContext()),
                           secure_context_mode);
  }

  // 2. Remove style present in context and not overriden by matched rules.
  EditingStyle* computed_style =
      MakeGarbageCollected<EditingStyle>(context, kEditingPropertiesInEffect);
  if (computed_style->mutable_style_) {
    if (!computed_style->mutable_style_->GetPropertyCSSValue(
            CSSPropertyID::kBackgroundColor)) {
      computed_style->mutable_style_->SetProperty(
          CSSPropertyID::kBackgroundColor, CSSValueID::kTransparent);
    }

    RemovePropertiesInStyle(computed_style->mutable_style_.Get(),
                            style_from_matched_rules);
    mutable_style_ = GetPropertiesNotIn(
        mutable_style_.Get(), element,
        computed_style->mutable_style_->EnsureCSSStyleDeclaration(
            element->GetExecutionContext()),
        secure_context_mode);
  }

  // 3. If this element is a span and has display: inline or float: none, remove
  // them unless they are overriden by rules. These rules are added by
  // serialization code to wrap text nodes.
  if (IsStyleSpanOrSpanWithOnlyStyleAttribute(element)) {
    if (!style_from_matched_rules->GetPropertyCSSValue(
            CSSPropertyID::kDisplay) &&
        GetProperty(CSSPropertyID::kDisplay) == CSSValueID::kInline)
      mutable_style_->RemoveProperty(CSSPropertyID::kDisplay);
    if (!style_from_matched_rules->GetPropertyCSSValue(CSSPropertyID::kFloat) &&
        GetProperty(CSSPropertyID::kFloat) == CSSValueID::kNone)
      mutable_style_->RemoveProperty(CSSPropertyID::kFloat);
  }
}

void EditingStyle::RemovePropertiesInElementDefaultStyle(Element* element) {
  if (!mutable_style_ || mutable_style_->IsEmpty())
    return;

  CSSPropertyValueSet* default_style = StyleFromMatchedRulesForElement(
      element, StyleResolver::kUAAndUserCSSRules);

  RemovePropertiesInStyle(mutable_style_.Get(), default_style);
}

void EditingStyle::ForceInline() {
  if (!mutable_style_) {
    mutable_style_ =
        MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  }
  const bool kPropertyIsImportant = true;
  mutable_style_->SetProperty(CSSPropertyID::kDisplay, CSSValueID::kInline,
                              kPropertyIsImportant);
}

int EditingStyle::LegacyFontSize(Document* document) const {
  const CSSValue* css_value =
      mutable_style_->GetPropertyCSSValue(CSSPropertyID::kFontSize);
  if (!css_value ||
      !(css_value->IsPrimitiveValue() || css_value->IsIdentifierValue()))
    return 0;
  return LegacyFontSizeFromCSSValue(document, css_value, is_monospace_font_,
                                    kAlwaysUseLegacyFontSize);
}

void EditingStyle::Trace(Visitor* visitor) const {
  visitor->Trace(mutable_style_);
  visitor->Trace(node_);
}

static void ReconcileTextDecorationProperties(
    MutableCSSPropertyValueSet* style,
    SecureContextMode secure_context_mode) {
  const CSSValue* text_decorations_in_effect =
      style->GetPropertyCSSValue(CSSPropertyID::kWebkitTextDecorationsInEffect);
  const CSSValue* text_decoration =
      style->GetPropertyCSSValue(CSSPropertyID::kTextDecorationLine);
  // "web_tests/editing/execCommand/insert-list-and-strikethrough.html" makes
  // both |textDecorationsInEffect| and |textDecoration| non-null.
  if (text_decorations_in_effect) {
    style->SetProperty(CSSPropertyID::kTextDecorationLine,
                       text_decorations_in_effect->CssText(),
                       /* important */ false, secure_context_mode);
    style->RemoveProperty(CSSPropertyID::kWebkitTextDecorationsInEffect);
    text_decoration = text_decorations_in_effect;
  }

  // If text-decoration is set to "none", remove the property because we don't
  // want to add redundant "text-decoration: none".
  if (text_decoration && !text_decoration->IsValueList())
    style->RemoveProperty(CSSPropertyID::kTextDecorationLine);
}

StyleChange::StyleChange(EditingStyle* style, const Position& position)
    : apply_bold_(false),
      apply_italic_(false),
      apply_underline_(false),
      apply_line_through_(false),
      apply_subscript_(false),
      apply_superscript_(false) {
  Document* document = position.GetDocument();
  if (!style || !style->Style() || !document || !document->GetFrame())
    return;
  Element* const element = AssociatedElementOf(position);
  if (!element)
    return;

  CSSComputedStyleDeclaration* const computed_style =
      MakeGarbageCollected<CSSComputedStyleDeclaration>(element);
  // FIXME: take care of background-color in effect
  // Note: editing/undo/redo-selection-modify-crash.html needs to pass
  // |element| to |GetPropertiesNotIn()| to remove "text-align:left".
  MutableCSSPropertyValueSet* mutable_style = GetPropertiesNotIn(
      style->Style(), element, computed_style,
      document->GetExecutionContext()->GetSecureContextMode());
  DCHECK(mutable_style);

  ReconcileTextDecorationProperties(
      mutable_style, document->GetExecutionContext()->GetSecureContextMode());
  if (!document->GetFrame()->GetEditor().ShouldStyleWithCSS())
    ExtractTextStyles(document, mutable_style,
                      computed_style->IsMonospaceFont());

  // Changing the whitespace style in a tab span would collapse the tab into a
  // space.
  if (IsTabHTMLSpanElementTextNode(position.AnchorNode()) ||
      IsTabHTMLSpanElement((position.AnchorNode())))
    mutable_style->RemoveProperty(CSSPropertyID::kWhiteSpace);

  // 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 (mutable_style->GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi) &&
      !style->Style()->GetPropertyCSSValue(CSSPropertyID::kDirection)) {
    mutable_style->SetProperty(
        CSSPropertyID::kDirection,
        style->Style()->GetPropertyValue(CSSPropertyID::kDirection),
        /* important */ false,
        document->GetExecutionContext()->GetSecureContextMode());
  }

  // Save the result for later
  css_style_ = mutable_style->AsText().StripWhiteSpace();
}

static void SetTextDecorationProperty(MutableCSSPropertyValueSet* style,
                                      const CSSValueList* new_text_decoration,
                                      CSSPropertyID property_id,
                                      SecureContextMode secure_context_mode) {
  if (new_text_decoration->length()) {
    style->SetProperty(property_id, new_text_decoration->CssText(),
                       style->PropertyIsImportant(property_id),
                       secure_context_mode);
  } else {
    // text-decoration: none is redundant since it does not remove any text
    // decorations.
    style->RemoveProperty(property_id);
  }
}

static bool GetPrimitiveValueNumber(CSSPropertyValueSet* style,
                                    CSSPropertyID property_id,
                                    float& number) {
  if (!style)
    return false;
  const CSSValue* value = style->GetPropertyCSSValue(property_id);
  const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value);
  if (!primitive_value)
    return false;
  number = primitive_value->GetFloatValue();
  return true;
}

void StyleChange::ExtractTextStyles(Document* document,
                                    MutableCSSPropertyValueSet* style,
                                    bool is_monospace_font) {
  DCHECK(style);

  float weight = 0;
  bool is_number =
      GetPrimitiveValueNumber(style, CSSPropertyID::kFontWeight, weight);
  if (GetIdentifierValue(style, CSSPropertyID::kFontWeight) ==
          CSSValueID::kBold ||
      (is_number && weight >= BoldThreshold())) {
    style->RemoveProperty(CSSPropertyID::kFontWeight);
    apply_bold_ = true;
  }

  CSSValueID font_style = GetIdentifierValue(style, CSSPropertyID::kFontStyle);
  if (font_style == CSSValueID::kItalic || font_style == CSSValueID::kOblique) {
    style->RemoveProperty(CSSPropertyID::kFontStyle);
    apply_italic_ = 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.
  const CSSValue* text_decoration =
      style->GetPropertyCSSValue(CSSPropertyID::kTextDecorationLine);
  if (const auto* text_decoration_value_list =
          DynamicTo<CSSValueList>(text_decoration)) {
    DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, underline,
                        (CSSIdentifierValue::Create(CSSValueID::kUnderline)));
    DEFINE_STATIC_LOCAL(Persistent<CSSIdentifierValue>, line_through,
                        (CSSIdentifierValue::Create(CSSValueID::kLineThrough)));
    CSSValueList* new_text_decoration = text_decoration_value_list->Copy();
    if (new_text_decoration->RemoveAll(*underline))
      apply_underline_ = true;
    if (new_text_decoration->RemoveAll(*line_through))
      apply_line_through_ = true;

    // If trimTextDecorations, delete underline and line-through
    SetTextDecorationProperty(
        style, new_text_decoration, CSSPropertyID::kTextDecorationLine,
        document->GetExecutionContext()->GetSecureContextMode());
  }

  CSSValueID vertical_align =
      GetIdentifierValue(style, CSSPropertyID::kVerticalAlign);
  switch (vertical_align) {
    case CSSValueID::kSub:
      style->RemoveProperty(CSSPropertyID::kVerticalAlign);
      apply_subscript_ = true;
      break;
    case CSSValueID::kSuper:
      style->RemoveProperty(CSSPropertyID::kVerticalAlign);
      apply_superscript_ = true;
      break;
    default:
      break;
  }

  if (style->GetPropertyCSSValue(CSSPropertyID::kColor)) {
    apply_font_color_ = GetFontColor(style).Serialized();
    style->RemoveProperty(CSSPropertyID::kColor);
  }

  apply_font_face_ = style->GetPropertyValue(CSSPropertyID::kFontFamily);
  // Remove double quotes for Outlook 2007 compatibility. See
  // https://bugs.webkit.org/show_bug.cgi?id=79448
  apply_font_face_.Replace('"', "");
  style->RemoveProperty(CSSPropertyID::kFontFamily);

  if (const CSSValue* font_size =
          style->GetPropertyCSSValue(CSSPropertyID::kFontSize)) {
    if (!font_size->IsPrimitiveValue() && !font_size->IsIdentifierValue()) {
      // Can't make sense of the number. Put no font size.
      style->RemoveProperty(CSSPropertyID::kFontSize);
    } else if (int legacy_font_size = LegacyFontSizeFromCSSValue(
                   document, font_size, is_monospace_font,
                   kUseLegacyFontSizeOnlyIfPixelValuesMatch)) {
      apply_font_size_ = String::Number(legacy_font_size);
      style->RemoveProperty(CSSPropertyID::kFontSize);
    }
  }
}

static void DiffTextDecorations(MutableCSSPropertyValueSet* style,
                                CSSPropertyID property_id,
                                const CSSValue* ref_text_decoration,
                                SecureContextMode secure_context_mode) {
  const CSSValue* text_decoration = style->GetPropertyCSSValue(property_id);
  const auto* values_in_text_decoration =
      DynamicTo<CSSValueList>(text_decoration);
  const auto* values_in_ref_text_decoration =
      DynamicTo<CSSValueList>(ref_text_decoration);
  if (!values_in_text_decoration || !values_in_ref_text_decoration)
    return;

  CSSValueList* new_text_decoration = values_in_text_decoration->Copy();

  for (wtf_size_t i = 0; i < values_in_ref_text_decoration->length(); i++)
    new_text_decoration->RemoveAll(values_in_ref_text_decoration->Item(i));

  SetTextDecorationProperty(style, new_text_decoration, property_id,
                            secure_context_mode);
}

static bool FontWeightIsBold(const CSSValue* font_weight) {
  if (auto* font_weight_identifier_value =
          DynamicTo<CSSIdentifierValue>(font_weight)) {
    // Because b tag can only bold text, there are only two states in plain
    // html: bold and not bold. Collapse all other values to either one of these
    // two states for editing purposes.

    switch (font_weight_identifier_value->GetValueID()) {
      case CSSValueID::kNormal:
        return false;
      case CSSValueID::kBold:
        return true;
      default:
        break;
    }
  }

  CHECK(To<CSSPrimitiveValue>(font_weight)->IsNumber());
  return To<CSSPrimitiveValue>(font_weight)->GetFloatValue() >= BoldThreshold();
}

static bool FontWeightNeedsResolving(const CSSValue* font_weight) {
  if (font_weight->IsPrimitiveValue())
    return false;
  auto* font_weight_identifier_value =
      DynamicTo<CSSIdentifierValue>(font_weight);
  if (!font_weight_identifier_value)
    return true;
  const CSSValueID value = font_weight_identifier_value->GetValueID();
  return value == CSSValueID::kLighter || value == CSSValueID::kBolder;
}

MutableCSSPropertyValueSet* GetPropertiesNotIn(
    CSSPropertyValueSet* style_with_redundant_properties,
    Node* node,
    CSSStyleDeclaration* base_style,
    SecureContextMode secure_context_mode) {
  DCHECK(style_with_redundant_properties);
  DCHECK(node);
  DCHECK(base_style);
  MutableCSSPropertyValueSet* result =
      style_with_redundant_properties->MutableCopy();

  result->RemoveEquivalentProperties(base_style);

  const CSSValue* base_text_decorations_in_effect =
      base_style->GetPropertyCSSValueInternal(
          CSSPropertyID::kWebkitTextDecorationsInEffect);
  DiffTextDecorations(result, CSSPropertyID::kTextDecorationLine,
                      base_text_decorations_in_effect, secure_context_mode);
  DiffTextDecorations(result, CSSPropertyID::kWebkitTextDecorationsInEffect,
                      base_text_decorations_in_effect, secure_context_mode);

  if (const CSSValue* base_font_weight =
          base_style->GetPropertyCSSValueInternal(CSSPropertyID::kFontWeight)) {
    if (const CSSValue* font_weight =
            result->GetPropertyCSSValue(CSSPropertyID::kFontWeight)) {
      if (!FontWeightNeedsResolving(font_weight) &&
          !FontWeightNeedsResolving(base_font_weight) &&
          (FontWeightIsBold(font_weight) == FontWeightIsBold(base_font_weight)))
        result->RemoveProperty(CSSPropertyID::kFontWeight);
    }
  }

  if (base_style->GetPropertyCSSValueInternal(CSSPropertyID::kColor) &&
      GetFontColor(result) == GetFontColor(base_style))
    result->RemoveProperty(CSSPropertyID::kColor);

  if (IsRedundantTextAlign(result, base_style, node))
    result->RemoveProperty(CSSPropertyID::kTextAlign);

  if (base_style->GetPropertyCSSValueInternal(
          CSSPropertyID::kBackgroundColor) &&
      GetBackgroundColor(result) == GetBackgroundColor(base_style))
    result->RemoveProperty(CSSPropertyID::kBackgroundColor);

  return result;
}

CSSValueID GetIdentifierValue(CSSPropertyValueSet* style,
                              CSSPropertyID property_id) {
  if (!style)
    return CSSValueID::kInvalid;
  const CSSValue* value = style->GetPropertyCSSValue(property_id);
  auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
  if (!identifier_value)
    return CSSValueID::kInvalid;
  return identifier_value->GetValueID();
}

CSSValueID GetIdentifierValue(CSSStyleDeclaration* style,
                              CSSPropertyID property_id) {
  if (!style)
    return CSSValueID::kInvalid;
  const CSSValue* value = style->GetPropertyCSSValueInternal(property_id);
  auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
  if (!identifier_value)
    return CSSValueID::kInvalid;
  return identifier_value->GetValueID();
}

int LegacyFontSizeFromCSSValue(Document* document,
                               const CSSValue* value,
                               bool is_monospace_font,
                               LegacyFontSizeMode mode) {
  if (const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) {
    if (primitive_value->IsLength()) {
      // TODO(crbug.com/979895): This doesn't seem to be handle math functions
      // correctly. This is the result of a refactoring, and may have revealed
      // an existing bug. Fix it if necessary.
      CSSPrimitiveValue::UnitType length_unit =
          primitive_value->IsNumericLiteralValue()
              ? To<CSSNumericLiteralValue>(primitive_value)->GetType()
              : CSSPrimitiveValue::UnitType::kPixels;
      if (!CSSPrimitiveValue::IsRelativeUnit(length_unit)) {
        double conversion =
            CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(
                length_unit);
        int pixel_font_size =
            clampTo<int>(primitive_value->GetDoubleValue() * conversion);
        int legacy_font_size = FontSizeFunctions::LegacyFontSize(
            document, pixel_font_size, is_monospace_font);
        // Use legacy font size only if pixel value matches exactly to that of
        // legacy font size.
        if (mode == kAlwaysUseLegacyFontSize ||
            FontSizeFunctions::FontSizeForKeyword(document, legacy_font_size,
                                                  is_monospace_font) ==
                pixel_font_size)
          return legacy_font_size;

        return 0;
      }
    }
  }

  if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
    if (identifier_value->GetValueID() == CSSValueID::kWebkitXxxLarge)
      return FontSizeFunctions::KeywordSize(CSSValueID::kXxxLarge) - 1;
    if (CSSValueID::kXSmall <= identifier_value->GetValueID() &&
        identifier_value->GetValueID() <= CSSValueID::kXxxLarge)
      return FontSizeFunctions::KeywordSize(identifier_value->GetValueID()) - 1;
  }

  return 0;
}

EditingTriState EditingStyle::SelectionHasStyle(const LocalFrame& frame,
                                                CSSPropertyID property_id,
                                                const String& value) {
  const SecureContextMode secure_context_mode =
      frame.DomWindow()->GetSecureContextMode();

  return MakeGarbageCollected<EditingStyle>(property_id, value,
                                            secure_context_mode)
      ->TriStateOfStyle(
          frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(),
          secure_context_mode);
}

}  // namespace blink
