// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"

#include <algorithm>
#include "base/optional.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/geometry/length.h"

namespace blink {

namespace {

enum class EBlockAlignment { kStart, kCenter, kEnd };

inline EBlockAlignment BlockAlignment(const ComputedStyle& style,
                                      const ComputedStyle& container_style) {
  bool start_auto = style.MarginStartUsing(container_style).IsAuto();
  bool end_auto = style.MarginEndUsing(container_style).IsAuto();
  if (start_auto || end_auto) {
    if (start_auto)
      return end_auto ? EBlockAlignment::kCenter : EBlockAlignment::kEnd;
    return EBlockAlignment::kStart;
  }

  // If none of the inline margins are auto, look for -webkit- text-align
  // values (which are really about block alignment). These are typically
  // mapped from the legacy "align" HTML attribute.
  switch (container_style.GetTextAlign()) {
    case ETextAlign::kWebkitLeft:
      if (container_style.IsLeftToRightDirection())
        return EBlockAlignment::kStart;
      return EBlockAlignment::kEnd;
    case ETextAlign::kWebkitRight:
      if (container_style.IsLeftToRightDirection())
        return EBlockAlignment::kEnd;
      return EBlockAlignment::kStart;
    case ETextAlign::kWebkitCenter:
      return EBlockAlignment::kCenter;
    default:
      return EBlockAlignment::kStart;
  }
}

inline bool InlineLengthMayChange(Length length,
                                  const NGConstraintSpace& new_space,
                                  const NGConstraintSpace& old_space) {
  // Percentage inline margins will affect the size if the size is unspecified
  // (auto and similar). So we need to check both available size and the
  // percentage resolution size in that case.
  bool is_unspecified =
      length.IsAuto() || length.IsFitContent() || length.IsFillAvailable();
  if (is_unspecified) {
    if (new_space.AvailableSize().inline_size !=
        old_space.AvailableSize().inline_size)
      return true;
  }
  if (is_unspecified || length.IsPercentOrCalc()) {
    if (new_space.PercentageResolutionInlineSize() !=
        old_space.PercentageResolutionInlineSize())
      return true;
  }
  return false;
}

inline bool BlockLengthMayChange(Length length,
                                 const NGConstraintSpace& new_space,
                                 const NGConstraintSpace& old_space) {
  if (length.IsFillAvailable()) {
    if (new_space.AvailableSize().block_size !=
        old_space.AvailableSize().block_size)
      return true;
  } else if (length.IsAuto() || length.IsPercentOrCalc()) {
    // Note that we check percentage resolution changes for 'auto' values here
    // (in addition to percent values). The reason is that percentage resolution
    // block sizes may be passed through auto-sized blocks, in some cases,
    // e.g. for anonymous blocks, and also in quirks mode.
    if (new_space.PercentageResolutionBlockSize() !=
        old_space.PercentageResolutionBlockSize())
      return true;
    if (new_space.ReplacedPercentageResolutionBlockSize() !=
        old_space.ReplacedPercentageResolutionBlockSize())
      return true;
  }
  return false;
}

}  // anonymous namespace

bool NeedMinMaxSizeForContentContribution(WritingMode mode,
                                          const ComputedStyle& style) {
  // During the intrinsic sizes pass percentages/calc() are defined to behave
  // like 'auto'. As a result we need to calculate the intrinsic sizes for any
  // children with percentages. E.g.
  // <div style="float:left;">
  //   <div style="width:30%;">text text</div>
  // </div>
  if (mode == WritingMode::kHorizontalTb) {
    return style.Width().IsIntrinsicOrAuto() ||
           style.Width().IsPercentOrCalc() || style.MinWidth().IsIntrinsic() ||
           style.MaxWidth().IsIntrinsic();
  }
  return style.Height().IsIntrinsicOrAuto() ||
         style.Height().IsPercentOrCalc() || style.MinHeight().IsIntrinsic() ||
         style.MaxHeight().IsIntrinsic();
}

LayoutUnit ResolveInlineLength(
    const NGConstraintSpace& constraint_space,
    const ComputedStyle& style,
    const base::Optional<MinMaxSize>& min_and_max,
    const Length& length,
    LengthResolveType type,
    LengthResolvePhase phase,
    const base::Optional<NGBoxStrut>& opt_border_padding) {
  DCHECK_GE(constraint_space.AvailableSize().inline_size, LayoutUnit());
  DCHECK_GE(constraint_space.PercentageResolutionInlineSize(), LayoutUnit());
  DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());

  if (constraint_space.IsAnonymous())
    return constraint_space.AvailableSize().inline_size;

  if (length.IsMaxSizeNone()) {
    DCHECK_EQ(type, LengthResolveType::kMaxSize);
    return LayoutUnit::Max();
  }

  NGBoxStrut border_and_padding =
      opt_border_padding ? *opt_border_padding
                         : ComputeBorders(constraint_space, style) +
                               ComputePadding(constraint_space, style);

  if (type == LengthResolveType::kMinSize && length.IsAuto())
    return border_and_padding.InlineSum();

  // Check if we shouldn't resolve a percentage/calc()/-webkit-fill-available
  // if we are in the intrinsic sizes phase.
  if (phase == LengthResolvePhase::kIntrinsic &&
      (length.IsPercentOrCalc() || length.GetType() == kFillAvailable)) {
    // min-width/min-height should be "0", i.e. no min limit is applied.
    if (type == LengthResolveType::kMinSize)
      return border_and_padding.InlineSum();

    // max-width/max-height becomes "infinity", i.e. no max limit is applied.
    if (type == LengthResolveType::kMaxSize)
      return LayoutUnit::Max();
  }

  switch (length.GetType()) {
    case kAuto:
    case kFillAvailable: {
      LayoutUnit content_size = constraint_space.AvailableSize().inline_size;
      NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
      return std::max(border_and_padding.InlineSum(),
                      content_size - margins.InlineSum());
    }
    case kPercent:
    case kFixed:
    case kCalculated: {
      LayoutUnit percentage_resolution_size =
          constraint_space.PercentageResolutionInlineSize();
      LayoutUnit value = ValueForLength(length, percentage_resolution_size);
      if (style.BoxSizing() == EBoxSizing::kContentBox) {
        value += border_and_padding.InlineSum();
      } else {
        value = std::max(border_and_padding.InlineSum(), value);
      }
      return value;
    }
    case kMinContent:
    case kMaxContent:
    case kFitContent: {
      DCHECK(min_and_max.has_value());
      LayoutUnit available_size = constraint_space.AvailableSize().inline_size;
      LayoutUnit value;
      if (length.IsMinContent()) {
        value = min_and_max->min_size;
      } else if (length.IsMaxContent() || available_size == LayoutUnit::Max()) {
        // If the available space is infinite, fit-content resolves to
        // max-content. See css-sizing section 2.1.
        value = min_and_max->max_size;
      } else {
        NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
        LayoutUnit fill_available =
            std::max(LayoutUnit(), available_size - margins.InlineSum());
        value = min_and_max->ShrinkToFit(fill_available);
      }
      return value;
    }
    case kDeviceWidth:
    case kDeviceHeight:
    case kExtendToZoom:
      NOTREACHED() << "These should only be used for viewport definitions";
      FALLTHROUGH;
    case kMaxSizeNone:
    default:
      NOTREACHED();
      return border_and_padding.InlineSum();
  }
}

LayoutUnit ResolveBlockLength(
    const NGConstraintSpace& constraint_space,
    const ComputedStyle& style,
    const Length& length,
    LayoutUnit content_size,
    LengthResolveType type,
    LengthResolvePhase phase,
    const base::Optional<NGBoxStrut>& opt_border_padding) {
  DCHECK_EQ(constraint_space.GetWritingMode(), style.GetWritingMode());

  if (constraint_space.IsAnonymous())
    return content_size;

  if (length.IsMaxSizeNone()) {
    DCHECK_EQ(type, LengthResolveType::kMaxSize);
    return LayoutUnit::Max();
  }

  NGBoxStrut border_and_padding =
      opt_border_padding ? *opt_border_padding
                         : ComputeBorders(constraint_space, style) +
                               ComputePadding(constraint_space, style);

  if (type == LengthResolveType::kMinSize && length.IsAuto())
    return border_and_padding.BlockSum();

  // Scrollable percentage-sized children of table cells, in the table
  // "measure" phase contribute nothing to the row height measurement.
  // See: https://drafts.csswg.org/css-tables-3/#row-layout
  if (length.IsPercentOrCalc() &&
      constraint_space.TableCellChildLayoutPhase() ==
          NGTableCellChildLayoutPhase::kMeasure &&
      (style.OverflowY() == EOverflow::kAuto ||
       style.OverflowY() == EOverflow::kScroll))
    return border_and_padding.BlockSum();

  // When the containing block size to resolve against is indefinite, we
  // cannot resolve percentages / calc() / -webkit-fill-available.
  bool size_is_unresolvable = false;
  if (length.IsPercentOrCalc()) {
    size_is_unresolvable =
        phase == LengthResolvePhase::kIntrinsic ||
        constraint_space.PercentageResolutionBlockSize() == NGSizeIndefinite;
  } else if (length.GetType() == kFillAvailable) {
    size_is_unresolvable =
        phase == LengthResolvePhase::kIntrinsic ||
        constraint_space.AvailableSize().block_size == NGSizeIndefinite;
  }
  if (size_is_unresolvable) {
    // min-width/min-height should be "0", i.e. no min limit is applied.
    if (type == LengthResolveType::kMinSize)
      return border_and_padding.BlockSum();

    // max-width/max-height becomes "infinity", i.e. no max limit is applied.
    if (type == LengthResolveType::kMaxSize)
      return LayoutUnit::Max();

    // width/height becomes "auto", so we can just return the content size.
    DCHECK_EQ(type, LengthResolveType::kContentSize);
    return content_size;
  }

  switch (length.GetType()) {
    case kFillAvailable: {
      LayoutUnit content_size = constraint_space.AvailableSize().block_size;
      NGBoxStrut margins = ComputeMarginsForSelf(constraint_space, style);
      return std::max(border_and_padding.BlockSum(),
                      content_size - margins.BlockSum());
    }
    case kPercent:
    case kFixed:
    case kCalculated: {
      LayoutUnit percentage_resolution_size =
          constraint_space.PercentageResolutionBlockSize();
      LayoutUnit value = ValueForLength(length, percentage_resolution_size);

      // Percentage-sized children of table cells, in the table "layout" phase,
      // pretend they have box-sizing: border-box.
      // TODO(crbug.com/285744): FF/Edge don't do this. Determine if there
      // would be compat issues for matching their behavior.
      if (style.BoxSizing() == EBoxSizing::kBorderBox ||
          (length.IsPercentOrCalc() &&
           constraint_space.TableCellChildLayoutPhase() ==
               NGTableCellChildLayoutPhase::kLayout)) {
        value = std::max(border_and_padding.BlockSum(), value);
      } else {
        value += border_and_padding.BlockSum();
      }
      return value;
    }
    case kAuto:
    case kMinContent:
    case kMaxContent:
    case kFitContent:
#if DCHECK_IS_ON()
      // Due to how content_size is calculated, it should always include border
      // and padding. We cannot check for this if we are block-fragmented,
      // though, because then the block-start border/padding may be in a
      // different fragmentainer than the block-end border/padding.
      if (content_size != LayoutUnit(-1) &&
          !constraint_space.HasBlockFragmentation())
        DCHECK_GE(content_size, border_and_padding.BlockSum());
#endif  // DCHECK_IS_ON()
      return content_size;
    case kDeviceWidth:
    case kDeviceHeight:
    case kExtendToZoom:
      NOTREACHED() << "These should only be used for viewport definitions";
      FALLTHROUGH;
    case kMaxSizeNone:
    default:
      NOTREACHED();
      return border_and_padding.BlockSum();
  }
}

LayoutUnit ResolveMarginPaddingLength(LayoutUnit percentage_resolution_size,
                                      const Length& length) {
  DCHECK_GE(percentage_resolution_size, LayoutUnit());

  // Margins and padding always get computed relative to the inline size:
  // https://www.w3.org/TR/CSS2/box.html#value-def-margin-width
  // https://www.w3.org/TR/CSS2/box.html#value-def-padding-width
  switch (length.GetType()) {
    case kAuto:
      return LayoutUnit();
    case kPercent:
    case kFixed:
    case kCalculated:
      return ValueForLength(length, percentage_resolution_size);
    case kMinContent:
    case kMaxContent:
    case kFillAvailable:
    case kFitContent:
    case kExtendToZoom:
    case kDeviceWidth:
    case kDeviceHeight:
    case kMaxSizeNone:
      FALLTHROUGH;
    default:
      NOTREACHED();
      return LayoutUnit();
  }
}

MinMaxSize ComputeMinAndMaxContentContribution(
    WritingMode writing_mode,
    const ComputedStyle& style,
    const base::Optional<MinMaxSize>& min_and_max) {
  // Synthesize a zero-sized constraint space for passing to
  // ResolveInlineLength.
  // The constraint space's writing mode has to match the style, so we can't
  // use the passed-in mode here.
  NGConstraintSpace space =
      NGConstraintSpaceBuilder(
          style.GetWritingMode(), style.GetWritingMode(),
          /* is_new_fc */ false)
          .ToConstraintSpace();

  LayoutUnit content_size =
      min_and_max ? min_and_max->max_size : NGSizeIndefinite;

  MinMaxSize computed_sizes;
  Length inline_size = writing_mode == WritingMode::kHorizontalTb
                           ? style.Width()
                           : style.Height();
  if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() ||
      inline_size.GetType() == kFillAvailable ||
      inline_size.GetType() == kFitContent) {
    CHECK(min_and_max.has_value());
    computed_sizes = *min_and_max;
  } else {
    if (IsParallelWritingMode(writing_mode, style.GetWritingMode())) {
      computed_sizes = ResolveInlineLength(
          space, style, min_and_max, inline_size,
          LengthResolveType::kContentSize, LengthResolvePhase::kIntrinsic);
    } else {
      computed_sizes = ResolveBlockLength(
          space, style, inline_size, content_size,
          LengthResolveType::kContentSize, LengthResolvePhase::kIntrinsic);
    }
  }

  Length max_length = writing_mode == WritingMode::kHorizontalTb
                          ? style.MaxWidth()
                          : style.MaxHeight();
  LayoutUnit max;
  if (IsParallelWritingMode(writing_mode, style.GetWritingMode())) {
    max = ResolveInlineLength(space, style, min_and_max, max_length,
                              LengthResolveType::kMaxSize,
                              LengthResolvePhase::kIntrinsic);
  } else {
    max = ResolveBlockLength(space, style, max_length, content_size,
                             LengthResolveType::kMaxSize,
                             LengthResolvePhase::kIntrinsic);
  }
  computed_sizes.Constrain(max);

  Length min_length = writing_mode == WritingMode::kHorizontalTb
                          ? style.MinWidth()
                          : style.MinHeight();
  LayoutUnit min;
  if (IsParallelWritingMode(writing_mode, style.GetWritingMode())) {
    min = ResolveInlineLength(space, style, min_and_max, min_length,
                              LengthResolveType::kMinSize,
                              LengthResolvePhase::kIntrinsic);
  } else {
    min = ResolveBlockLength(space, style, min_length, content_size,
                             LengthResolveType::kMinSize,
                             LengthResolvePhase::kIntrinsic);
  }
  computed_sizes.Encompass(min);

  return computed_sizes;
}

MinMaxSize ComputeMinAndMaxContentContribution(
    const ComputedStyle& parent_style,
    NGLayoutInputNode child,
    const MinMaxSizeInput& input) {
  const ComputedStyle& child_style = child.Style();
  WritingMode parent_writing_mode = parent_style.GetWritingMode();
  LayoutBox* box = child.GetLayoutBox();

  if (box->NeedsPreferredWidthsRecalculation()) {
    // Some objects (when there's an intrinsic ratio) have their min/max inline
    // size affected by the block size of their container. We don't really know
    // whether the containing block of this child did change or is going to
    // change size. However, this is our only opportunity to make sure that it
    // gets its min/max widths calculated.
    box->SetPreferredLogicalWidthsDirty();
  }

  if (IsParallelWritingMode(parent_writing_mode,
                            child_style.GetWritingMode())) {
    if (!box->PreferredLogicalWidthsDirty()) {
      return {box->MinPreferredLogicalWidth(), box->MaxPreferredLogicalWidth()};
    }
    // Tables are special; even if a width is specified, they may end up being
    // sized different. So we just always let the table code handle this.
    // Replaced elements may size themselves using aspect ratios and block
    // sizes, so we pass that on as well.
    if (box->IsTable() || box->IsTablePart() || box->IsLayoutReplaced()) {
      return {box->MinPreferredLogicalWidth(), box->MaxPreferredLogicalWidth()};
    }
  }

  base::Optional<MinMaxSize> minmax;
  if (NeedMinMaxSizeForContentContribution(parent_writing_mode, child_style)) {
    // We need to set up a constraint space with correct fallback available
    // inline size in case of orthogonal children.
    NGConstraintSpace indefinite_constraint_space;
    const NGConstraintSpace* child_constraint_space = nullptr;
    if (!IsParallelWritingMode(parent_writing_mode,
                               child_style.GetWritingMode())) {
      indefinite_constraint_space =
          CreateIndefiniteConstraintSpaceForChild(parent_style, child);
      child_constraint_space = &indefinite_constraint_space;
    }
    minmax = child.ComputeMinMaxSize(parent_writing_mode, input,
                                     child_constraint_space);
  }

  MinMaxSize sizes = ComputeMinAndMaxContentContribution(parent_writing_mode,
                                                         child_style, minmax);
  if (IsParallelWritingMode(parent_writing_mode, child_style.GetWritingMode()))
    box->SetPreferredLogicalWidthsFromNG(sizes);
  return sizes;
}

LayoutUnit ComputeInlineSizeForFragment(
    const NGConstraintSpace& space,
    NGLayoutInputNode node,
    const base::Optional<NGBoxStrut>& border_padding,
    const MinMaxSize* override_minmax) {
  if (space.IsFixedSizeInline())
    return space.AvailableSize().inline_size;

  const ComputedStyle& style = node.Style();
  Length logical_width = style.LogicalWidth();
  if (logical_width.IsAuto() && space.IsShrinkToFit())
    logical_width = Length(kFitContent);

  LayoutBox* box = node.GetLayoutBox();
  // If we have usable cached min/max intrinsic sizes, use those if we can. They
  // will normally also be constrained to {min,max}-inline-size, but not if
  // percentages are involved. In such cases we'll have to calculate and apply
  // the constraints on our own.
  if (!box->PreferredLogicalWidthsDirty() && !override_minmax &&
      !style.LogicalMinWidth().IsPercentOrCalc() &&
      !style.LogicalMaxWidth().IsPercentOrCalc()) {
    if (logical_width.GetType() == kFitContent) {
      // This is not as easy as {min, max}.ShrinkToFit() because we also need
      // to subtract inline margins from the available size. The code in
      // ResolveInlineLength knows how to handle that, just call that.

      MinMaxSize min_and_max = {box->MinPreferredLogicalWidth(),
                                box->MaxPreferredLogicalWidth()};
      return ResolveInlineLength(space, style, min_and_max, logical_width,
                                 LengthResolveType::kContentSize,
                                 LengthResolvePhase::kLayout);
    }
    if (logical_width.GetType() == kMinContent)
      return box->MinPreferredLogicalWidth();
    if (logical_width.GetType() == kMaxContent)
      return box->MaxPreferredLogicalWidth();
  }

  base::Optional<MinMaxSize> min_and_max;
  if (NeedMinMaxSize(space, style)) {
    if (override_minmax) {
      min_and_max = *override_minmax;
    } else {
      min_and_max = node.ComputeMinMaxSize(space.GetWritingMode(),
                                           MinMaxSizeInput(), &space);
      // Cache these computed values
      MinMaxSize contribution = ComputeMinAndMaxContentContribution(
          style.GetWritingMode(), style, min_and_max);
      box->SetPreferredLogicalWidthsFromNG(contribution);
    }
  }

  LayoutUnit extent = ResolveInlineLength(
      space, style, min_and_max, logical_width, LengthResolveType::kContentSize,
      LengthResolvePhase::kLayout, border_padding);

  LayoutUnit max = ResolveInlineLength(
      space, style, min_and_max, style.LogicalMaxWidth(),
      LengthResolveType::kMaxSize, LengthResolvePhase::kLayout, border_padding);
  LayoutUnit min = ResolveInlineLength(
      space, style, min_and_max, style.LogicalMinWidth(),
      LengthResolveType::kMinSize, LengthResolvePhase::kLayout, border_padding);
  return ConstrainByMinMax(extent, min, max);
}

namespace {

// Computes the block-size for a fragment, ignoring the fixed block-size if set.
LayoutUnit ComputeBlockSizeForFragmentInternal(
    const NGConstraintSpace& constraint_space,
    const ComputedStyle& style,
    LayoutUnit content_size,
    const base::Optional<NGBoxStrut>& border_padding) {
  LayoutUnit extent =
      ResolveBlockLength(constraint_space, style, style.LogicalHeight(),
                         content_size, LengthResolveType::kContentSize,
                         LengthResolvePhase::kLayout, border_padding);
  if (extent == NGSizeIndefinite) {
    DCHECK_EQ(content_size, NGSizeIndefinite);
    return extent;
  }

  LayoutUnit max = ResolveBlockLength(
      constraint_space, style, style.LogicalMaxHeight(), content_size,
      LengthResolveType::kMaxSize, LengthResolvePhase::kLayout, border_padding);
  LayoutUnit min = ResolveBlockLength(
      constraint_space, style, style.LogicalMinHeight(), content_size,
      LengthResolveType::kMinSize, LengthResolvePhase::kLayout, border_padding);

  return ConstrainByMinMax(extent, min, max);
}

}  // namespace

LayoutUnit ComputeBlockSizeForFragment(
    const NGConstraintSpace& constraint_space,
    const ComputedStyle& style,
    LayoutUnit content_size,
    const base::Optional<NGBoxStrut>& border_padding) {
  if (constraint_space.IsFixedSizeBlock())
    return constraint_space.AvailableSize().block_size;

  return ComputeBlockSizeForFragmentInternal(constraint_space, style,
                                             content_size, border_padding);
}

// Computes size for a replaced element.
NGLogicalSize ComputeReplacedSize(
    const NGLayoutInputNode& node,
    const NGConstraintSpace& space,
    const base::Optional<MinMaxSize>& child_minmax) {
  DCHECK(node.IsReplaced());

  NGLogicalSize replaced_size;

  NGLogicalSize default_intrinsic_size;
  base::Optional<LayoutUnit> computed_inline_size;
  base::Optional<LayoutUnit> computed_block_size;
  NGLogicalSize aspect_ratio;

  node.IntrinsicSize(&default_intrinsic_size, &computed_inline_size,
                     &computed_block_size, &aspect_ratio);

  const ComputedStyle& style = node.Style();
  Length inline_length = style.LogicalWidth();
  Length block_length = style.LogicalHeight();

  // Compute inline size
  if (inline_length.IsAuto()) {
    if (block_length.IsAuto() || aspect_ratio.IsEmpty()) {
      // Use intrinsic values if inline_size cannot be computed from block_size.
      if (computed_inline_size.has_value())
        replaced_size.inline_size = computed_inline_size.value();
      else
        replaced_size.inline_size = default_intrinsic_size.inline_size;
      replaced_size.inline_size +=
          (ComputeBorders(space, style) + ComputePadding(space, style))
              .InlineSum();
    } else {
      // inline_size is computed from block_size.
      replaced_size.inline_size =
          ResolveBlockLength(
              space, style, block_length, default_intrinsic_size.block_size,
              LengthResolveType::kContentSize, LengthResolvePhase::kLayout) *
          aspect_ratio.inline_size / aspect_ratio.block_size;
    }
  } else {
    // inline_size is resolved directly.
    replaced_size.inline_size = ResolveInlineLength(
        space, style, child_minmax, inline_length,
        LengthResolveType::kContentSize, LengthResolvePhase::kLayout);
  }

  // Compute block size
  if (block_length.IsAuto()) {
    if (inline_length.IsAuto() || aspect_ratio.IsEmpty()) {
      // Use intrinsic values if block_size cannot be computed from inline_size.
      if (computed_block_size.has_value())
        replaced_size.block_size = LayoutUnit(computed_block_size.value());
      else
        replaced_size.block_size = default_intrinsic_size.block_size;
      replaced_size.block_size +=
          (ComputeBorders(space, style) + ComputePadding(space, style))
              .BlockSum();
    } else {
      // block_size is computed from inline_size.
      replaced_size.block_size =
          ResolveInlineLength(space, style, child_minmax, inline_length,
                              LengthResolveType::kContentSize,
                              LengthResolvePhase::kLayout) *
          aspect_ratio.block_size / aspect_ratio.inline_size;
    }
  } else {
    replaced_size.block_size = ResolveBlockLength(
        space, style, block_length, default_intrinsic_size.block_size,
        LengthResolveType::kContentSize, LengthResolvePhase::kLayout);
  }
  return replaced_size;
}

bool SizeMayChange(const ComputedStyle& style,
                   const NGConstraintSpace& new_space,
                   const NGConstraintSpace& old_space) {
  DCHECK_EQ(new_space.IsFixedSizeInline(), old_space.IsFixedSizeInline());
  DCHECK_EQ(new_space.IsFixedSizeBlock(), old_space.IsFixedSizeBlock());

  // Go through all length properties, and, depending on length type
  // (percentages, auto, etc.), check whether the constraint spaces differ in
  // such a way that the resulting size *may* change. There are currently many
  // possible false-positive situations here, as we don't rule out length
  // changes that won't have any effect on the final size (e.g. if inline-size
  // is 100px, max-inline-size is 50%, and percentage resolution inline size
  // changes from 1000px to 500px). If the constraint space has "fixed" size in
  // a dimension, we can skip checking properties in that dimension and just
  // look for available size changes, since that's how a "fixed" constraint
  // space works.
  if (new_space.IsFixedSizeInline()) {
    if (new_space.AvailableSize().inline_size !=
        old_space.AvailableSize().inline_size)
      return true;
  } else {
    if (InlineLengthMayChange(style.LogicalWidth(), new_space, old_space) ||
        InlineLengthMayChange(style.LogicalMaxWidth(), new_space, old_space) ||
        InlineLengthMayChange(style.LogicalMaxWidth(), new_space, old_space))
      return true;
  }

  if (new_space.IsFixedSizeBlock()) {
    if (new_space.AvailableSize().block_size !=
        old_space.AvailableSize().block_size)
      return true;
  } else {
    if (BlockLengthMayChange(style.LogicalHeight(), new_space, old_space) ||
        BlockLengthMayChange(style.LogicalMinHeight(), new_space, old_space) ||
        BlockLengthMayChange(style.LogicalMaxHeight(), new_space, old_space))
      return true;
  }

  if (new_space.PercentageResolutionInlineSize() !=
      old_space.PercentageResolutionInlineSize()) {
    // Percentage-based padding is resolved against the inline content box size
    // of the containing block.
    if (style.PaddingTop().IsPercentOrCalc() ||
        style.PaddingRight().IsPercentOrCalc() ||
        style.PaddingBottom().IsPercentOrCalc() ||
        style.PaddingLeft().IsPercentOrCalc())
      return true;
  }

  return false;
}

int ResolveUsedColumnCount(int computed_count,
                           LayoutUnit computed_size,
                           LayoutUnit used_gap,
                           LayoutUnit available_size) {
  if (computed_size == NGSizeIndefinite) {
    DCHECK(computed_count);
    return computed_count;
  }
  DCHECK_GT(computed_size, LayoutUnit());
  int count_from_width =
      ((available_size + used_gap) / (computed_size + used_gap)).ToInt();
  count_from_width = std::max(1, count_from_width);
  if (!computed_count)
    return count_from_width;
  return std::max(1, std::min(computed_count, count_from_width));
}

int ResolveUsedColumnCount(LayoutUnit available_size,
                           const ComputedStyle& style) {
  LayoutUnit computed_column_inline_size =
      style.HasAutoColumnWidth()
          ? NGSizeIndefinite
          : std::max(LayoutUnit(1), LayoutUnit(style.ColumnWidth()));
  LayoutUnit gap = ResolveUsedColumnGap(available_size, style);
  int computed_count = style.ColumnCount();
  return ResolveUsedColumnCount(computed_count, computed_column_inline_size,
                                gap, available_size);
}

LayoutUnit ResolveUsedColumnInlineSize(int computed_count,
                                       LayoutUnit computed_size,
                                       LayoutUnit used_gap,
                                       LayoutUnit available_size) {
  int used_count = ResolveUsedColumnCount(computed_count, computed_size,
                                          used_gap, available_size);
  return std::max(((available_size + used_gap) / used_count) - used_gap,
                  LayoutUnit());
}

LayoutUnit ResolveUsedColumnInlineSize(LayoutUnit available_size,
                                       const ComputedStyle& style) {
  // Should only attempt to resolve this if columns != auto.
  DCHECK(!style.HasAutoColumnCount() || !style.HasAutoColumnWidth());

  LayoutUnit computed_size =
      style.HasAutoColumnWidth()
          ? NGSizeIndefinite
          : std::max(LayoutUnit(1), LayoutUnit(style.ColumnWidth()));
  int computed_count = style.HasAutoColumnCount() ? 0 : style.ColumnCount();
  LayoutUnit used_gap = ResolveUsedColumnGap(available_size, style);
  return ResolveUsedColumnInlineSize(computed_count, computed_size, used_gap,
                                     available_size);
}

LayoutUnit ResolveUsedColumnGap(LayoutUnit available_size,
                                const ComputedStyle& style) {
  if (style.ColumnGap().IsNormal())
    return LayoutUnit(style.GetFontDescription().ComputedPixelSize());
  return ValueForLength(style.ColumnGap().GetLength(), available_size);
}

NGPhysicalBoxStrut ComputePhysicalMargins(
    const ComputedStyle& style,
    LayoutUnit percentage_resolution_size) {
  if (!style.HasMargin())
    return NGPhysicalBoxStrut();

  NGPhysicalBoxStrut physical_dim;
  physical_dim.left = ResolveMarginPaddingLength(percentage_resolution_size,
                                                 style.MarginLeft());
  physical_dim.right = ResolveMarginPaddingLength(percentage_resolution_size,
                                                  style.MarginRight());
  physical_dim.top =
      ResolveMarginPaddingLength(percentage_resolution_size, style.MarginTop());
  physical_dim.bottom = ResolveMarginPaddingLength(percentage_resolution_size,
                                                   style.MarginBottom());
  return physical_dim;
}

NGBoxStrut ComputeMarginsFor(const NGConstraintSpace& constraint_space,
                             const ComputedStyle& style,
                             const NGConstraintSpace& compute_for) {
  if (constraint_space.IsAnonymous())
    return NGBoxStrut();
  LayoutUnit percentage_resolution_size =
      constraint_space.PercentageResolutionInlineSizeForParentWritingMode();
  return ComputePhysicalMargins(style, percentage_resolution_size)
      .ConvertToLogical(compute_for.GetWritingMode(), compute_for.Direction());
}

NGBoxStrut ComputeMinMaxMargins(const ComputedStyle& parent_style,
                                NGLayoutInputNode child) {
  // An inline child just produces line-boxes which don't have any margins.
  if (child.IsInline())
    return NGBoxStrut();

  Length inline_start_margin_length =
      child.Style().MarginStartUsing(parent_style);
  Length inline_end_margin_length = child.Style().MarginEndUsing(parent_style);

  // TODO(ikilpatrick): We may want to re-visit calculated margins at some
  // point. Currently "margin-left: calc(10px + 50%)" will resolve to 0px, but
  // 10px would be more correct, (as percentages resolve to zero).
  NGBoxStrut margins;
  if (inline_start_margin_length.IsFixed())
    margins.inline_start = LayoutUnit(inline_start_margin_length.Value());
  if (inline_end_margin_length.IsFixed())
    margins.inline_end = LayoutUnit(inline_end_margin_length.Value());

  return margins;
}

NGBoxStrut ComputeBorders(const NGConstraintSpace& constraint_space,
                          const ComputedStyle& style) {
  // If we are producing an anonymous fragment (e.g. a column) we shouldn't
  // have any borders.
  if (constraint_space.IsAnonymous())
    return NGBoxStrut();

  NGBoxStrut borders;
  borders.inline_start = LayoutUnit(style.BorderStartWidth());
  borders.inline_end = LayoutUnit(style.BorderEndWidth());
  borders.block_start = LayoutUnit(style.BorderBeforeWidth());
  borders.block_end = LayoutUnit(style.BorderAfterWidth());
  return borders;
}

NGBoxStrut ComputeBorders(const NGConstraintSpace& constraint_space,
                          const NGLayoutInputNode node) {
  // If we are producing an anonymous fragment (e.g. a column), it has no
  // borders, padding or scrollbars. Using the ones from the container can only
  // cause trouble.
  if (constraint_space.IsAnonymous())
    return NGBoxStrut();

  if (node.GetLayoutBox()->IsTableCell()) {
    LayoutBox* box = node.GetLayoutBox();
    return NGBoxStrut(box->BorderStart(), box->BorderEnd(), box->BorderBefore(),
                      box->BorderAfter());
  }
  return ComputeBorders(constraint_space, node.Style());
}

NGBoxStrut ComputeIntrinsicPadding(const NGConstraintSpace& constraint_space,
                                   const NGLayoutInputNode node) {
  if (constraint_space.IsAnonymous() || !node.IsTableCell())
    return NGBoxStrut();

  // At the moment we just access the values set by the parent table layout.
  // Once we have a NGTableLayoutAlgorithm this should pass the intrinsic
  // padding via the constraint space object.

  // TODO(karlo): intrinsic padding can sometimes be negative; that seems
  // insane, but works in the old code; in NG it trips DCHECKs.
  return {LayoutUnit(), LayoutUnit(), node.IntrinsicPaddingBlockStart(),
          node.IntrinsicPaddingBlockEnd()};
}

NGBoxStrut ComputePadding(const NGConstraintSpace& constraint_space,
                          const ComputedStyle& style) {
  // If we are producing an anonymous fragment (e.g. a column) we shouldn't
  // have any padding.
  if (constraint_space.IsAnonymous())
    return NGBoxStrut();

  LayoutUnit percentage_resolution_size =
      constraint_space.PercentageResolutionInlineSizeForParentWritingMode();
  NGBoxStrut padding;
  padding.inline_start = ResolveMarginPaddingLength(percentage_resolution_size,
                                                    style.PaddingStart());
  padding.inline_end = ResolveMarginPaddingLength(percentage_resolution_size,
                                                  style.PaddingEnd());
  padding.block_start = ResolveMarginPaddingLength(percentage_resolution_size,
                                                   style.PaddingBefore());
  padding.block_end = ResolveMarginPaddingLength(percentage_resolution_size,
                                                 style.PaddingAfter());
  return padding;
}


bool NeedsInlineSizeToResolveLineLeft(const ComputedStyle& style,
                                      const ComputedStyle& container_style) {
  // In RTL, there's no block alignment where we can guarantee that line-left
  // doesn't depend on the inline size of a fragment.
  if (IsRtl(container_style.Direction()))
    return true;

  return BlockAlignment(style, container_style) != EBlockAlignment::kStart;
}

void ResolveInlineMargins(const ComputedStyle& style,
                          const ComputedStyle& container_style,
                          LayoutUnit available_inline_size,
                          LayoutUnit inline_size,
                          NGBoxStrut* margins) {
  DCHECK(margins) << "Margins cannot be NULL here";
  const LayoutUnit used_space = inline_size + margins->InlineSum();
  const LayoutUnit available_space = available_inline_size - used_space;
  if (available_space > LayoutUnit()) {
    EBlockAlignment alignment = BlockAlignment(style, container_style);
    if (alignment == EBlockAlignment::kCenter)
      margins->inline_start += available_space / 2;
    else if (alignment == EBlockAlignment::kEnd)
      margins->inline_start += available_space;
  }
  margins->inline_end =
      available_inline_size - inline_size - margins->inline_start;
}

LayoutUnit LineOffsetForTextAlign(ETextAlign text_align,
                                  TextDirection direction,
                                  LayoutUnit space_left,
                                  LayoutUnit trailing_spaces_width) {
  bool is_ltr = IsLtr(direction);
  if (text_align == ETextAlign::kStart || text_align == ETextAlign::kJustify)
    text_align = is_ltr ? ETextAlign::kLeft : ETextAlign::kRight;
  else if (text_align == ETextAlign::kEnd)
    text_align = is_ltr ? ETextAlign::kRight : ETextAlign::kLeft;

  switch (text_align) {
    case ETextAlign::kLeft:
    case ETextAlign::kWebkitLeft: {
      // The direction of the block should determine what happens with wide
      // lines. In particular with RTL blocks, wide lines should still spill
      // out to the left.
      if (is_ltr)
        return LayoutUnit();
      return space_left.ClampPositiveToZero();
    }
    case ETextAlign::kRight:
    case ETextAlign::kWebkitRight: {
      // In RTL, trailing spaces appear on the left of the line.
      if (UNLIKELY(!is_ltr))
        return space_left - trailing_spaces_width;
      // Wide lines spill out of the block based off direction.
      // So even if text-align is right, if direction is LTR, wide lines
      // should overflow out of the right side of the block.
      if (space_left > LayoutUnit())
        return space_left;
      return LayoutUnit();
    }
    case ETextAlign::kCenter:
    case ETextAlign::kWebkitCenter: {
      if (is_ltr)
        return (space_left / 2).ClampNegativeToZero();
      // In RTL, trailing spaces appear on the left of the line.
      if (space_left > LayoutUnit())
        return (space_left / 2).ClampNegativeToZero() - trailing_spaces_width;
      // In RTL, wide lines should spill out to the left, same as kRight.
      return space_left - trailing_spaces_width;
    }
    default:
      NOTREACHED();
      return LayoutUnit();
  }
}

LayoutUnit InlineOffsetForTextAlign(const ComputedStyle& container_style,
                                    LayoutUnit space_left) {
  TextDirection direction = container_style.Direction();
  LayoutUnit line_offset = LineOffsetForTextAlign(
      container_style.GetTextAlign(), direction, space_left, LayoutUnit());
  return IsLtr(direction) ? line_offset : space_left - line_offset;
}

bool ClampScrollbarToContentBox(NGBoxStrut* scrollbars,
                                LayoutUnit content_box_inline_size) {
  DCHECK(scrollbars->InlineSum());
  if (scrollbars->InlineSum() <= content_box_inline_size)
    return false;
  if (scrollbars->inline_end) {
    DCHECK(!scrollbars->inline_start);
    scrollbars->inline_end = content_box_inline_size;
  } else {
    DCHECK(scrollbars->inline_start);
    scrollbars->inline_start = content_box_inline_size;
  }
  return true;
}

NGBoxStrut CalculateBorderScrollbarPadding(
    const NGConstraintSpace& constraint_space,
    const NGBlockNode node) {
  // If we are producing an anonymous fragment (e.g. a column), it has no
  // borders, padding or scrollbars. Using the ones from the container can only
  // cause trouble.
  if (constraint_space.IsAnonymous())
    return NGBoxStrut();
  return ComputeBorders(constraint_space, node) +
         ComputePadding(constraint_space, node.Style()) +
         ComputeIntrinsicPadding(constraint_space, node) +
         node.GetScrollbarSizes();
}

NGLogicalSize CalculateBorderBoxSize(
    const NGConstraintSpace& constraint_space,
    const NGBlockNode& node,
    LayoutUnit block_content_size,
    const base::Optional<NGBoxStrut>& border_padding) {
  // If we have a percentage size, we need to set the
  // HasPercentHeightDescendants flag correctly so that flexboz knows it may
  // need to redo layout and can also do some performance optimizations.
  if (node.Style().LogicalHeight().IsPercentOrCalc() ||
      node.Style().LogicalMinHeight().IsPercentOrCalc() ||
      node.Style().LogicalMaxHeight().IsPercentOrCalc() ||
      (node.GetLayoutBox()->IsFlexItemIncludingNG() &&
       node.Style().FlexBasis().IsPercentOrCalc())) {
    // This call has the side-effect of setting HasPercentHeightDescendants
    // correctly.
    node.GetLayoutBox()->ComputePercentageLogicalHeight(Length(0, kPercent));
  }

  return NGLogicalSize(
      ComputeInlineSizeForFragment(constraint_space, node, border_padding),
      ComputeBlockSizeForFragment(constraint_space, node.Style(),
                                  block_content_size, border_padding));
}

NGLogicalSize ShrinkAvailableSize(NGLogicalSize size, const NGBoxStrut& inset) {
  DCHECK_NE(size.inline_size, NGSizeIndefinite);
  size.inline_size -= inset.InlineSum();
  size.inline_size = std::max(size.inline_size, LayoutUnit());

  if (size.block_size != NGSizeIndefinite) {
    size.block_size -= inset.BlockSum();
    size.block_size = std::max(size.block_size, LayoutUnit());
  }

  return size;
}

namespace {

// Implements the common part of the child percentage size calculation. Deals
// with how percentages are propagated from parent to child in quirks mode.
NGLogicalSize AdjustChildPercentageSizeForQuirksAndFlex(
    const NGConstraintSpace& space,
    const NGBlockNode node,
    NGLogicalSize child_percentage_size,
    LayoutUnit parent_percentage_block_size) {
  // Flex items may have a fixed block-size, but children shouldn't resolve
  // their percentages against this.
  if (space.IsFixedSizeBlock() && !space.FixedSizeBlockIsDefinite()) {
    DCHECK(node.IsFlexItem());
    child_percentage_size.block_size = NGSizeIndefinite;
    return child_percentage_size;
  }

  // In quirks mode the percentage resolution height is passed from parent to
  // child.
  // https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk
  if (child_percentage_size.block_size == NGSizeIndefinite &&
      node.GetDocument().InQuirksMode() && !node.Style().IsDisplayTableType() &&
      !node.Style().HasOutOfFlowPosition()) {
    child_percentage_size.block_size = parent_percentage_block_size;
  }

  return child_percentage_size;
}

}  // namespace

NGLogicalSize CalculateChildPercentageSize(
    const NGConstraintSpace& space,
    const NGBlockNode node,
    const NGLogicalSize& child_available_size) {
  // Anonymous block or spaces should pass the percent size straight through.
  if (space.IsAnonymous() || node.IsAnonymousBlock())
    return space.PercentageResolutionSize();

  NGLogicalSize child_percentage_size = child_available_size;

  bool is_table_cell_in_measure_phase =
      node.IsTableCell() && !space.IsFixedSizeBlock();

  // Table cells which are measuring their content, force their children to
  // have an indefinite percentage resolution size.
  if (is_table_cell_in_measure_phase) {
    child_percentage_size.block_size = NGSizeIndefinite;
    return child_percentage_size;
  }

  // Table cell children don't apply the "percentage-quirk". I.e. if their
  // percentage resolution block-size is indefinite, they don't pass through
  // their parent's percentage resolution block-size.
  if (space.TableCellChildLayoutPhase() !=
      NGTableCellChildLayoutPhase::kNotTableCellChild)
    return child_percentage_size;

  return AdjustChildPercentageSizeForQuirksAndFlex(
      space, node, child_percentage_size,
      space.PercentageResolutionBlockSize());
}

NGLogicalSize CalculateReplacedChildPercentageSize(
    const NGConstraintSpace& space,
    const NGBlockNode node,
    NGLogicalSize border_box_size,
    const NGBoxStrut& border_scrollbar_padding,
    const NGBoxStrut& border_padding) {
  // Anonymous block or spaces should pass the percent size straight through.
  if (space.IsAnonymous() || node.IsAnonymousBlock())
    return space.ReplacedPercentageResolutionSize();

  bool has_resolvable_block_size = !node.Style().LogicalHeight().IsAuto() ||
                                   !node.Style().LogicalMinHeight().IsAuto();

  bool is_table_cell_in_layout_phase =
      node.IsTableCell() && space.IsFixedSizeBlock();

  // Table cells in the "layout" phase have a fixed block-size. However
  // replaced children should resolve their percentages against the size given
  // in the "measure" phase.
  //
  // To handle this we recalculate the border-box block-size, ignoring the
  // fixed size constraint.
  if (is_table_cell_in_layout_phase && has_resolvable_block_size) {
    border_box_size.block_size = ComputeBlockSizeForFragmentInternal(
        space, node.Style(), NGSizeIndefinite, border_padding);
  }

  NGLogicalSize child_percentage_size =
      ShrinkAvailableSize(border_box_size, border_scrollbar_padding);

  return AdjustChildPercentageSizeForQuirksAndFlex(
      space, node, child_percentage_size,
      space.ReplacedPercentageResolutionBlockSize());
}

}  // namespace blink
