/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "third_party/blink/renderer/core/css/resolver/style_adjuster.h"

#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/container_node.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_computed_style.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_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/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_operations.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"

namespace blink {

using namespace HTMLNames;

namespace {

TouchAction AdjustTouchActionForElement(TouchAction touch_action,
                                        const ComputedStyle& style,
                                        Element* element) {
  bool is_child_document =
      element && element == element->GetDocument().documentElement() &&
      element->GetDocument().LocalOwner();
  if (style.ScrollsOverflow() || is_child_document)
    return touch_action | TouchAction::kTouchActionPan;
  return touch_action;
}

bool ShouldForceLegacyLayout(const ComputedStyle& style,
                             const ComputedStyle& layout_parent_style,
                             const Element& element) {
  // Form controls are not supported yet.
  if (element.ShouldForceLegacyLayout())
    return true;

  // When the actual parent (to inherit style from) doesn't have a layout box
  // (display:contents), it may not have been switched over to forcing legacy
  // layout, even if it's inside a subtree that should use legacy. Check with
  // the layout parent as well, so that we don't risk switching back to LayoutNG
  // when we shouldn't.
  if (layout_parent_style.ForceLegacyLayout())
    return true;

  const Document& document = element.GetDocument();

  // TODO(layout-dev): Once LayoutNG handles inline content editable, we
  // should get rid of following code fragment.
  if (!RuntimeEnabledFeatures::EditingNGEnabled()) {
    if (style.UserModify() != EUserModify::kReadOnly || document.InDesignMode())
      return true;
  }

  if (style.Display() == EDisplay::kWebkitBox ||
      style.Display() == EDisplay::kWebkitInlineBox)
    return true;

  if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
    // Disable NG for the entire subtree if we're establishing a block
    // fragmentation context.
    if (style.SpecifiesColumns() || style.IsOverflowPaged())
      return true;
    if (document.Printing()) {
      // This needs to be discovered on the root element.
      DCHECK_EQ(element, document.documentElement());
      return true;
    }
  }

  // The custom container is laid out by the legacy engine. Its children may
  // not establish new formatting contexts, so we need to protect against
  // re-entering LayoutNG there.
  if (style.Display() == EDisplay::kLayoutCustom ||
      style.Display() == EDisplay::kInlineLayoutCustom)
    return true;

  // 'text-combine-upright' property is not supported yet.
  if (style.HasTextCombine() && !style.IsHorizontalWritingMode())
    return true;

  return false;
}

}  // namespace

static EDisplay EquivalentBlockDisplay(EDisplay display) {
  switch (display) {
    case EDisplay::kBlock:
    case EDisplay::kTable:
    case EDisplay::kWebkitBox:
    case EDisplay::kFlex:
    case EDisplay::kGrid:
    case EDisplay::kListItem:
    case EDisplay::kFlowRoot:
    case EDisplay::kLayoutCustom:
      return display;
    case EDisplay::kInlineTable:
      return EDisplay::kTable;
    case EDisplay::kWebkitInlineBox:
      return EDisplay::kWebkitBox;
    case EDisplay::kInlineFlex:
      return EDisplay::kFlex;
    case EDisplay::kInlineGrid:
      return EDisplay::kGrid;
    case EDisplay::kInlineLayoutCustom:
      return EDisplay::kLayoutCustom;

    case EDisplay::kContents:
    case EDisplay::kInline:
    case EDisplay::kInlineBlock:
    case EDisplay::kTableRowGroup:
    case EDisplay::kTableHeaderGroup:
    case EDisplay::kTableFooterGroup:
    case EDisplay::kTableRow:
    case EDisplay::kTableColumnGroup:
    case EDisplay::kTableColumn:
    case EDisplay::kTableCell:
    case EDisplay::kTableCaption:
      return EDisplay::kBlock;
    case EDisplay::kNone:
      NOTREACHED();
      return display;
  }
  NOTREACHED();
  return EDisplay::kBlock;
}

static bool IsOutermostSVGElement(const Element* element) {
  return element && element->IsSVGElement() &&
         ToSVGElement(*element).IsOutermostSVGSVGElement();
}

// CSS requires text-decoration to be reset at each DOM element for
// inline blocks, inline tables, shadow DOM crossings, floating elements,
// and absolute or relatively positioned elements. Outermost <svg> roots are
// considered to be atomic inline-level.
static bool DoesNotInheritTextDecoration(const ComputedStyle& style,
                                         const Element* element) {
  return style.Display() == EDisplay::kInlineTable ||
         style.Display() == EDisplay::kInlineBlock ||
         style.Display() == EDisplay::kWebkitInlineBox ||
         IsAtShadowBoundary(element) || style.IsFloating() ||
         style.HasOutOfFlowPosition() || IsOutermostSVGElement(element) ||
         IsHTMLRTElement(element);
}

// Certain elements (<a>, <font>) override text decoration colors.  "The font
// element is expected to override the color of any text decoration that spans
// the text of the element to the used value of the element's 'color' property."
// (https://html.spec.whatwg.org/multipage/rendering.html#phrasing-content-3)
// The <a> behavior is non-standard.
static bool OverridesTextDecorationColors(const Element* element) {
  return element &&
         (IsHTMLFontElement(element) || IsHTMLAnchorElement(element));
}

// FIXME: This helper is only needed because pseudoStyleForElement passes a null
// element to adjustComputedStyle, so we can't just use element->isInTopLayer().
static bool IsInTopLayer(const Element* element, const ComputedStyle& style) {
  return (element && element->IsInTopLayer()) ||
         style.StyleType() == kPseudoIdBackdrop;
}

static bool LayoutParentStyleForcesZIndexToCreateStackingContext(
    const ComputedStyle& layout_parent_style) {
  return layout_parent_style.IsDisplayFlexibleOrGridBox();
}

void StyleAdjuster::AdjustStyleForEditing(ComputedStyle& style) {
  if (style.UserModify() != EUserModify::kReadWritePlaintextOnly)
    return;
  // Collapsing whitespace is harmful in plain-text editing.
  if (style.WhiteSpace() == EWhiteSpace::kNormal)
    style.SetWhiteSpace(EWhiteSpace::kPreWrap);
  else if (style.WhiteSpace() == EWhiteSpace::kNowrap)
    style.SetWhiteSpace(EWhiteSpace::kPre);
  else if (style.WhiteSpace() == EWhiteSpace::kPreLine)
    style.SetWhiteSpace(EWhiteSpace::kPreWrap);
}

static void AdjustStyleForFirstLetter(ComputedStyle& style) {
  if (style.StyleType() != kPseudoIdFirstLetter)
    return;

  // Force inline display (except for floating first-letters).
  style.SetDisplay(style.IsFloating() ? EDisplay::kBlock : EDisplay::kInline);

  // CSS2 says first-letter can't be positioned.
  style.SetPosition(EPosition::kStatic);
}

static void AdjustStyleForHTMLElement(ComputedStyle& style,
                                      HTMLElement& element) {
  // <div> and <span> are the most common elements on the web, we skip all the
  // work for them.
  if (IsHTMLDivElement(element) || IsHTMLSpanElement(element))
    return;

  if (IsHTMLTableCellElement(element)) {
    if (style.WhiteSpace() == EWhiteSpace::kWebkitNowrap) {
      // Figure out if we are really nowrapping or if we should just
      // use normal instead. If the width of the cell is fixed, then
      // we don't actually use NOWRAP.
      if (style.Width().IsFixed())
        style.SetWhiteSpace(EWhiteSpace::kNormal);
      else
        style.SetWhiteSpace(EWhiteSpace::kNowrap);
    }
    return;
  }

  if (auto* image = ToHTMLImageElementOrNull(element)) {
    if (image->IsCollapsed() || style.Display() == EDisplay::kContents)
      style.SetDisplay(EDisplay::kNone);
    return;
  }

  if (IsHTMLTableElement(element)) {
    // Tables never support the -webkit-* values for text-align and will reset
    // back to the default.
    if (style.GetTextAlign() == ETextAlign::kWebkitLeft ||
        style.GetTextAlign() == ETextAlign::kWebkitCenter ||
        style.GetTextAlign() == ETextAlign::kWebkitRight)
      style.SetTextAlign(ETextAlign::kStart);
    return;
  }

  if (IsHTMLFrameElement(element) || IsHTMLFrameSetElement(element)) {
    // Frames and framesets never honor position:relative or position:absolute.
    // This is necessary to fix a crash where a site tries to position these
    // objects. They also never honor display nor floating.
    style.SetPosition(EPosition::kStatic);
    style.SetDisplay(EDisplay::kBlock);
    style.SetFloating(EFloat::kNone);
    return;
  }

  if (IsHTMLFrameElementBase(element)) {
    if (style.Display() == EDisplay::kContents) {
      style.SetDisplay(EDisplay::kNone);
      return;
    }
    // Frames cannot overflow (they are always the size we ask them to be).
    // Some compositing code paths may try to draw scrollbars anyhow.
    style.SetOverflowX(EOverflow::kVisible);
    style.SetOverflowY(EOverflow::kVisible);
    return;
  }

  if (IsHTMLRTElement(element)) {
    // Ruby text does not support float or position. This might change with
    // evolution of the specification.
    style.SetPosition(EPosition::kStatic);
    style.SetFloating(EFloat::kNone);
    return;
  }

  if (IsHTMLLegendElement(element) && style.Display() != EDisplay::kContents) {
    // Allow any blockified display value for legends. Note that according to
    // the spec, this shouldn't affect computed style (like we do here).
    // Instead, the display override should be determined during box creation,
    // and even then only be applied to the rendered legend inside a
    // fieldset. However, Blink determines the rendered legend during layout
    // instead of during layout object creation, and also generally makes
    // assumptions that the computed display value is the one to use.
    style.SetDisplay(EquivalentBlockDisplay(style.Display()));
    return;
  }

  if (IsHTMLMarqueeElement(element)) {
    // For now, <marquee> requires an overflow clip to work properly.
    style.SetOverflowX(EOverflow::kHidden);
    style.SetOverflowY(EOverflow::kHidden);
    return;
  }

  if (IsHTMLTextAreaElement(element)) {
    // Textarea considers overflow visible as auto.
    style.SetOverflowX(style.OverflowX() == EOverflow::kVisible
                           ? EOverflow::kAuto
                           : style.OverflowX());
    style.SetOverflowY(style.OverflowY() == EOverflow::kVisible
                           ? EOverflow::kAuto
                           : style.OverflowY());
    if (style.Display() == EDisplay::kContents)
      style.SetDisplay(EDisplay::kNone);
    return;
  }

  if (IsHTMLPlugInElement(element)) {
    style.SetRequiresAcceleratedCompositingForExternalReasons(
        ToHTMLPlugInElement(element).ShouldAccelerate());
    if (style.Display() == EDisplay::kContents)
      style.SetDisplay(EDisplay::kNone);
    return;
  }

  if (style.Display() == EDisplay::kContents) {
    // See https://drafts.csswg.org/css-display/#unbox-html
    // Some of these elements are handled with other adjustments above.
    if (IsHTMLBRElement(element) || IsHTMLWBRElement(element) ||
        IsHTMLMeterElement(element) || IsHTMLProgressElement(element) ||
        IsHTMLCanvasElement(element) || IsHTMLMediaElement(element) ||
        IsHTMLInputElement(element) || IsHTMLTextAreaElement(element) ||
        IsHTMLSelectElement(element)) {
      style.SetDisplay(EDisplay::kNone);
    }
  }
}

static void AdjustOverflow(ComputedStyle& style) {
  DCHECK(style.OverflowX() != EOverflow::kVisible ||
         style.OverflowY() != EOverflow::kVisible);

  if (style.Display() == EDisplay::kTable ||
      style.Display() == EDisplay::kInlineTable) {
    // Tables only support overflow:hidden and overflow:visible and ignore
    // anything else, see https://drafts.csswg.org/css2/visufx.html#overflow. As
    // a table is not a block container box the rules for resolving conflicting
    // x and y values in CSS Overflow Module Level 3 do not apply. Arguably
    // overflow-x and overflow-y aren't allowed on tables but all UAs allow it.
    if (style.OverflowX() != EOverflow::kHidden)
      style.SetOverflowX(EOverflow::kVisible);
    if (style.OverflowY() != EOverflow::kHidden)
      style.SetOverflowY(EOverflow::kVisible);
    // If we are left with conflicting overflow values for the x and y axes on a
    // table then resolve both to OverflowVisible. This is interoperable
    // behaviour but is not specced anywhere.
    if (style.OverflowX() == EOverflow::kVisible)
      style.SetOverflowY(EOverflow::kVisible);
    else if (style.OverflowY() == EOverflow::kVisible)
      style.SetOverflowX(EOverflow::kVisible);
  } else if (style.OverflowX() == EOverflow::kVisible &&
             style.OverflowY() != EOverflow::kVisible) {
    // If either overflow value is not visible, change to auto.
    // FIXME: Once we implement pagination controls, overflow-x should default
    // to hidden if overflow-y is set to -webkit-paged-x or -webkit-page-y. For
    // now, we'll let it default to auto so we can at least scroll through the
    // pages.
    style.SetOverflowX(EOverflow::kAuto);
  } else if (style.OverflowY() == EOverflow::kVisible &&
             style.OverflowX() != EOverflow::kVisible) {
    style.SetOverflowY(EOverflow::kAuto);
  }

  // Menulists should have visible overflow
  if (style.Appearance() == kMenulistPart) {
    style.SetOverflowX(EOverflow::kVisible);
    style.SetOverflowY(EOverflow::kVisible);
  }
}

static void AdjustStyleForDisplay(ComputedStyle& style,
                                  const ComputedStyle& layout_parent_style,
                                  Document* document) {
  if (style.Display() == EDisplay::kBlock && !style.IsFloating())
    return;

  if (style.Display() == EDisplay::kContents)
    return;

  // FIXME: Don't support this mutation for pseudo styles like first-letter or
  // first-line, since it's not completely clear how that should work.
  if (style.Display() == EDisplay::kInline &&
      style.StyleType() == kPseudoIdNone &&
      style.GetWritingMode() != layout_parent_style.GetWritingMode())
    style.SetDisplay(EDisplay::kInlineBlock);

  // We do not honor position: relative or sticky for table rows, headers, and
  // footers. This is correct for position: relative in CSS2.1 (and caused a
  // crash in containingBlock() on some sites) and position: sticky is defined
  // as following position: relative behavior for table elements. It is
  // incorrect for CSS3.
  if ((style.Display() == EDisplay::kTableHeaderGroup ||
       style.Display() == EDisplay::kTableRowGroup ||
       style.Display() == EDisplay::kTableFooterGroup ||
       style.Display() == EDisplay::kTableRow) &&
      style.HasInFlowPosition())
    style.SetPosition(EPosition::kStatic);

  // Cannot support position: sticky for table columns and column groups because
  // current code is only doing background painting through columns / column
  // groups.
  if ((style.Display() == EDisplay::kTableColumnGroup ||
       style.Display() == EDisplay::kTableColumn) &&
      style.GetPosition() == EPosition::kSticky)
    style.SetPosition(EPosition::kStatic);

  // writing-mode does not apply to table row groups, table column groups, table
  // rows, and table columns.
  // FIXME: Table cells should be allowed to be perpendicular or flipped with
  // respect to the table, though.
  if (style.Display() == EDisplay::kTableColumn ||
      style.Display() == EDisplay::kTableColumnGroup ||
      style.Display() == EDisplay::kTableFooterGroup ||
      style.Display() == EDisplay::kTableHeaderGroup ||
      style.Display() == EDisplay::kTableRow ||
      style.Display() == EDisplay::kTableRowGroup ||
      style.Display() == EDisplay::kTableCell) {
    style.SetWritingMode(layout_parent_style.GetWritingMode());
    style.UpdateFontOrientation();
  }

  // FIXME: Since we don't support block-flow on flexible boxes yet, disallow
  // setting of block-flow to anything other than TopToBottomWritingMode.
  // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
  if (style.GetWritingMode() != WritingMode::kHorizontalTb &&
      (style.Display() == EDisplay::kWebkitBox ||
       style.Display() == EDisplay::kWebkitInlineBox)) {
    style.SetWritingMode(WritingMode::kHorizontalTb);
    style.UpdateFontOrientation();
  }

  if (layout_parent_style.IsDisplayFlexibleOrGridBox()) {
    style.SetFloating(EFloat::kNone);
    style.SetDisplay(EquivalentBlockDisplay(style.Display()));

    // We want to count vertical percentage paddings/margins on flex items
    // because our current behavior is different from the spec and we want to
    // gather compatibility data.
    if (style.PaddingBefore().IsPercentOrCalc() ||
        style.PaddingAfter().IsPercentOrCalc()) {
      UseCounter::Count(document,
                        WebFeature::kFlexboxPercentagePaddingVertical);
    }
    if (style.MarginBefore().IsPercentOrCalc() ||
        style.MarginAfter().IsPercentOrCalc()) {
      UseCounter::Count(document, WebFeature::kFlexboxPercentageMarginVertical);
    }
  } else if (layout_parent_style.IsDisplayLayoutCustomBox()) {
    // Blockify the children of a LayoutCustom.
    style.SetDisplay(EquivalentBlockDisplay(style.Display()));
  }
}

static void AdjustEffectiveTouchAction(ComputedStyle& style,
                                       const ComputedStyle& parent_style,
                                       Element* element,
                                       bool is_svg_root) {
  TouchAction inherited_action = parent_style.GetEffectiveTouchAction();

  bool is_replaced_canvas =
      element && IsHTMLCanvasElement(element) &&
      element->GetDocument().GetFrame() &&
      element->GetDocument().CanExecuteScripts(kNotAboutToExecuteScript);
  bool is_non_replaced_inline_elements =
      style.IsDisplayInlineType() &&
      !(style.IsDisplayReplacedType() || is_svg_root ||
        IsHTMLImageElement(element) || is_replaced_canvas);
  bool is_table_row_or_column = style.IsDisplayTableRowOrColumnType();
  bool is_layout_object_needed =
      element && element->LayoutObjectIsNeeded(style);

  TouchAction element_touch_action = TouchAction::kTouchActionAuto;
  // Touch actions are only supported by elements that support both the CSS
  // width and height properties.
  // See https://www.w3.org/TR/pointerevents/#the-touch-action-css-property.
  if (!is_non_replaced_inline_elements && !is_table_row_or_column &&
      is_layout_object_needed) {
    element_touch_action = style.GetTouchAction();
  }

  if (!element) {
    style.SetEffectiveTouchAction(element_touch_action & inherited_action);
    return;
  }

  bool is_child_document = element == element->GetDocument().documentElement();

  // Apply touch action inherited from parent frame.
  if (is_child_document && element->GetDocument().GetFrame()) {
    inherited_action &=
        TouchAction::kTouchActionPan |
        element->GetDocument().GetFrame()->InheritedEffectiveTouchAction();
  }

  // The effective touch action is the intersection of the touch-action values
  // of the current element and all of its ancestors up to the one that
  // implements the gesture. Since panning is implemented by the scroller it is
  // re-enabled for scrolling elements.
  // The panning-restricted cancellation should also apply to iframes, so we
  // allow (panning & local touch action) on the first descendant element of a
  // iframe element.
  inherited_action =
      AdjustTouchActionForElement(inherited_action, style, element);

  TouchAction enforced_by_policy = TouchAction::kTouchActionNone;
  if (element->GetDocument().IsVerticalScrollEnforced())
    enforced_by_policy = TouchAction::kTouchActionPanY;

  // Apply the adjusted parent effective touch actions.
  style.SetEffectiveTouchAction((element_touch_action & inherited_action) |
                                enforced_by_policy);

  // Propagate touch action to child frames.
  if (element->IsFrameOwnerElement()) {
    Frame* content_frame = ToHTMLFrameOwnerElement(element)->ContentFrame();
    if (content_frame) {
      content_frame->SetInheritedEffectiveTouchAction(
          style.GetEffectiveTouchAction());
    }
  }
}

void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
                                        Element* element) {
  DCHECK(state.LayoutParentStyle());
  DCHECK(state.ParentStyle());
  ComputedStyle& style = state.StyleRef();
  const ComputedStyle& parent_style = *state.ParentStyle();
  const ComputedStyle& layout_parent_style = *state.LayoutParentStyle();

  if (element && element->IsHTMLElement() &&
      (style.Display() != EDisplay::kNone ||
       element->LayoutObjectIsNeeded(style))) {
    AdjustStyleForHTMLElement(style, ToHTMLElement(*element));
  }
  if (style.Display() != EDisplay::kNone) {
    bool is_document_element =
        element && element->GetDocument().documentElement() == element;
    // Per the spec, position 'static' and 'relative' in the top layer compute
    // to 'absolute'. Root elements that are in the top layer should just
    // be left alone because the fullscreen.css doesn't apply any style to
    // them.
    if (IsInTopLayer(element, style) && !is_document_element &&
        (style.GetPosition() == EPosition::kStatic ||
         style.GetPosition() == EPosition::kRelative))
      style.SetPosition(EPosition::kAbsolute);

    // Absolute/fixed positioned elements, floating elements and the document
    // element need block-like outside display.
    if (style.Display() != EDisplay::kContents &&
        (style.HasOutOfFlowPosition() || style.IsFloating()))
      style.SetDisplay(EquivalentBlockDisplay(style.Display()));

    if (is_document_element)
      style.SetDisplay(EquivalentBlockDisplay(style.Display()));

    // We don't adjust the first letter style earlier because we may change the
    // display setting in adjustStyeForTagName() above.
    AdjustStyleForFirstLetter(style);

    AdjustStyleForDisplay(style, layout_parent_style,
                          element ? &element->GetDocument() : nullptr);

    // If this is a child of a LayoutCustom, we need the name of the parent
    // layout function for invalidation purposes.
    if (layout_parent_style.IsDisplayLayoutCustomBox()) {
      style.SetDisplayLayoutCustomParentName(
          layout_parent_style.DisplayLayoutCustomName());
    }
  } else {
    AdjustStyleForFirstLetter(style);
  }

  // Make sure our z-index value is only applied if the object is positioned.
  if (style.GetPosition() == EPosition::kStatic &&
      !LayoutParentStyleForcesZIndexToCreateStackingContext(
          layout_parent_style)) {
    style.SetIsStackingContext(false);
    // TODO(alancutter): Avoid altering z-index here.
    if (!style.HasAutoZIndex())
      style.SetZIndex(0);
  } else if (!style.HasAutoZIndex()) {
    style.SetIsStackingContext(true);
  }

  if (style.OverflowX() != EOverflow::kVisible ||
      style.OverflowY() != EOverflow::kVisible)
    AdjustOverflow(style);

  if (DoesNotInheritTextDecoration(style, element))
    style.ClearAppliedTextDecorations();
  else
    style.RestoreParentTextDecorations(parent_style);
  style.ApplyTextDecorations(
      parent_style.VisitedDependentColor(GetCSSPropertyTextDecorationColor()),
      OverridesTextDecorationColors(element));

  // Cull out any useless layers and also repeat patterns into additional
  // layers.
  style.AdjustBackgroundLayers();
  style.AdjustMaskLayers();

  // Let the theme also have a crack at adjusting the style.
  if (style.HasAppearance())
    LayoutTheme::GetTheme().AdjustStyle(style, element);

  AdjustStyleForEditing(style);

  bool is_svg_root = false;
  bool is_svg_element = element && element->IsSVGElement();

  if (is_svg_element) {
    is_svg_root = ToSVGElement(element)->IsOutermostSVGSVGElement();
    if (!is_svg_root) {
      // Only the root <svg> element in an SVG document fragment tree honors css
      // position.
      style.SetPosition(ComputedStyleInitialValues::InitialPosition());
    }

    if (style.Display() == EDisplay::kContents &&
        (is_svg_root ||
         (!IsSVGSVGElement(element) && !IsSVGGElement(element) &&
          !IsSVGUseElement(element) && !IsSVGTSpanElement(element)))) {
      // According to the CSS Display spec[1], nested <svg> elements, <g>,
      // <use>, and <tspan> elements are not rendered and their children are
      // "hoisted". For other elements display:contents behaves as display:none.
      //
      // [1] https://drafts.csswg.org/css-display/#unbox-svg
      style.SetDisplay(EDisplay::kNone);
    }

    // SVG text layout code expects us to be a block-level style element.
    if ((IsSVGForeignObjectElement(*element) || IsSVGTextElement(*element)) &&
        style.IsDisplayInlineType())
      style.SetDisplay(EDisplay::kBlock);

    // Columns don't apply to svg text elements.
    if (IsSVGTextElement(*element))
      style.ClearMultiCol();
  }

  // If this node is sticky it marks the creation of a sticky subtree, which we
  // must track to properly handle document lifecycle in some cases.
  //
  // It is possible that this node is already in a sticky subtree (i.e. we have
  // nested sticky nodes) - in that case the bit will already be set via
  // inheritance from the ancestor and there is no harm to setting it again.
  if (style.GetPosition() == EPosition::kSticky)
    style.SetSubtreeIsSticky(true);

  // If the inherited value of justify-items includes the 'legacy'
  // keyword (plus 'left', 'right' or 'center'), 'legacy' computes to
  // the the inherited value.  Otherwise, 'auto' computes to 'normal'.
  if (parent_style.JustifyItemsPositionType() == ItemPositionType::kLegacy &&
      style.JustifyItemsPosition() == ItemPosition::kLegacy) {
    style.SetJustifyItems(parent_style.JustifyItems());
  }

  AdjustEffectiveTouchAction(style, parent_style, element, is_svg_root);

  bool is_media_control =
      element && element->ShadowPseudoId().StartsWith("-webkit-media-controls");
  if (is_media_control && style.Appearance() == kNoControlPart) {
    // For compatibility reasons if the element is a media control and the
    // -webkit-appearance is none then we should clear the background image.
    if (!StyleResolver::HasAuthorBackground(state)) {
      style.MutableBackgroundInternal().ClearImage();
    }
  }

  if (element && style.TextOverflow() == ETextOverflow::kEllipsis) {
    const AtomicString& pseudo_id = element->ShadowPseudoId();
    if (pseudo_id == "-webkit-input-placeholder" ||
        pseudo_id == "-internal-input-suggested") {
      TextControlElement* text_control =
          ToTextControl(element->OwnerShadowHost());
      DCHECK(text_control);
      // TODO(futhark@chromium.org): We force clipping text overflow for focused
      // input elements since we don't want to render ellipsis during editing.
      // We should do this as a general solution which also includes
      // contenteditable elements being edited. The computed style should not
      // change, but LayoutBlockFlow::ShouldTruncateOverflowingText() should
      // instead return false when text is being edited inside that block.
      // https://crbug.com/814954
      style.SetTextOverflow(text_control->ValueForTextOverflow());
    }
  }

  if (RuntimeEnabledFeatures::LayoutNGEnabled() && !style.ForceLegacyLayout() &&
      element &&
      ShouldForceLegacyLayout(style, layout_parent_style, *element)) {
    style.SetForceLegacyLayout(true);
  }
}
}  // namespace blink
