/*
 * This file is part of the layout object implementation for KHTML.
 *
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2003 Apple Computer, Inc.
 *
 * 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/layout/layout_deprecated_flexible_box.h"

#include <algorithm>
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"

namespace blink {

class FlexBoxIterator {
 public:
  FlexBoxIterator(LayoutDeprecatedFlexibleBox* parent)
      : box_(parent), largest_ordinal_(1) {
    forward_ = box_->StyleRef().BoxDirection() == EBoxDirection::kNormal;
    if (!forward_) {
      // No choice, since we're going backwards, we have to find out the highest
      // ordinal up front.
      LayoutBox* child = box_->FirstChildBox();
      while (child) {
        if (child->StyleRef().BoxOrdinalGroup() > largest_ordinal_)
          largest_ordinal_ = child->StyleRef().BoxOrdinalGroup();
        child = child->NextSiblingBox();
      }
    }

    Reset();
  }

  void Reset() {
    current_child_ = nullptr;
    natural_current_child_ = nullptr;
    ordinal_iteration_ = -1;
  }

  LayoutBox* First() {
    Reset();
    return Next();
  }

  LayoutBox* Next() {
    do {
      if (!current_child_) {
        ++ordinal_iteration_;

        if (!ordinal_iteration_) {
          current_ordinal_ = forward_ ? 1 : largest_ordinal_;
        } else {
          if (static_cast<size_t>(ordinal_iteration_) >=
              ordinal_values_.size() + 1)
            return nullptr;

          // Only copy+sort the values once per layout even if the iterator is
          // reset.
          if (ordinal_values_.size() != sorted_ordinal_values_.size()) {
            CopyToVector(ordinal_values_, sorted_ordinal_values_);
            std::sort(sorted_ordinal_values_.begin(),
                      sorted_ordinal_values_.end());
          }
          current_ordinal_ =
              forward_ ? sorted_ordinal_values_[ordinal_iteration_ - 1]
                       : sorted_ordinal_values_[sorted_ordinal_values_.size() -
                                                ordinal_iteration_];
        }

        current_child_ =
            forward_ ? box_->FirstChildBox() : box_->LastChildBox();
      } else {
        current_child_ = forward_ ? current_child_->NextSiblingBox()
                                  : current_child_->PreviousSiblingBox();
      }

      if (current_child_ && NotFirstOrdinalValue())
        ordinal_values_.insert(current_child_->StyleRef().BoxOrdinalGroup());
    } while (!current_child_ || (!current_child_->IsAnonymous() &&
                                 current_child_->StyleRef().BoxOrdinalGroup() !=
                                     current_ordinal_));

    // This peice of code just exists for detecting if this iterator actually
    // does something other than returning the default order.
    if (!natural_current_child_)
      natural_current_child_ = box_->FirstChildBox();
    else
      natural_current_child_ = natural_current_child_->NextSiblingBox();

    if (natural_current_child_ != current_child_) {
      UseCounter::Count(box_->GetDocument(),
                        WebFeature::kWebkitBoxNotDefaultOrder);
    }

    return current_child_;
  }

 private:
  bool NotFirstOrdinalValue() {
    unsigned first_ordinal_value = forward_ ? 1 : largest_ordinal_;
    return current_ordinal_ == first_ordinal_value &&
           current_child_->StyleRef().BoxOrdinalGroup() != first_ordinal_value;
  }

  LayoutDeprecatedFlexibleBox* box_;
  LayoutBox* current_child_;
  LayoutBox* natural_current_child_;
  bool forward_;
  unsigned current_ordinal_;
  unsigned largest_ordinal_;
  HashSet<unsigned> ordinal_values_;
  Vector<unsigned> sorted_ordinal_values_;
  int ordinal_iteration_;
};

// Helper methods for obtaining the last line, computing line counts and heights
// for line counts
// (crawling into blocks).
static bool ShouldCheckLines(LayoutBlockFlow* block_flow) {
  return !block_flow->IsFloatingOrOutOfFlowPositioned() &&
         block_flow->StyleRef().Height().IsAuto();
}

static int GetHeightForLineCount(const LayoutBlockFlow* block_flow,
                                 int line_count,
                                 bool include_bottom,
                                 int& count) {
  if (block_flow->ChildrenInline()) {
    for (RootInlineBox* box = block_flow->FirstRootBox(); box;
         box = box->NextRootBox()) {
      if (++count == line_count)
        return (box->LineBottomWithLeading() +
                (include_bottom ? (block_flow->BorderBottom() +
                                   block_flow->PaddingBottom())
                                : LayoutUnit()))
            .ToInt();
    }
    return -1;
  }

  LayoutBox* normal_flow_child_without_lines = nullptr;
  for (LayoutBox* obj = block_flow->FirstChildBox(); obj;
       obj = obj->NextSiblingBox()) {
    auto* block_flow = DynamicTo<LayoutBlockFlow>(obj);
    if (block_flow && ShouldCheckLines(block_flow)) {
      int result = GetHeightForLineCount(block_flow, line_count, false, count);
      if (result != -1)
        return (result + obj->Location().Y() +
                (include_bottom ? (block_flow->BorderBottom() +
                                   block_flow->PaddingBottom())
                                : LayoutUnit()))
            .ToInt();
    } else if (!obj->IsFloatingOrOutOfFlowPositioned()) {
      normal_flow_child_without_lines = obj;
    }
  }
  if (normal_flow_child_without_lines && line_count == 0)
    return (normal_flow_child_without_lines->Location().Y() +
            normal_flow_child_without_lines->Size().Height())
        .ToInt();

  return -1;
}

static RootInlineBox* LineAtIndex(const LayoutBlockFlow* block_flow, int i) {
  DCHECK_GE(i, 0);

  if (block_flow->ChildrenInline()) {
    for (RootInlineBox* box = block_flow->FirstRootBox(); box;
         box = box->NextRootBox()) {
      if (!i--)
        return box;
    }
    return nullptr;
  }
  for (LayoutObject* child = block_flow->FirstChild(); child;
       child = child->NextSibling()) {
    auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
    if (!child_block_flow)
      continue;
    if (!ShouldCheckLines(child_block_flow))
      continue;
    if (RootInlineBox* box = LineAtIndex(child_block_flow, i))
      return box;
  }

  return nullptr;
}

static int LineCount(const LayoutBlockFlow* block_flow,
                     const RootInlineBox* stop_root_inline_box = nullptr,
                     bool* found = nullptr) {
  int count = 0;
  if (block_flow->ChildrenInline()) {
    for (RootInlineBox* box = block_flow->FirstRootBox(); box;
         box = box->NextRootBox()) {
      count++;
      if (box == stop_root_inline_box) {
        if (found)
          *found = true;
        break;
      }
    }
    return count;
  }
  for (LayoutObject* obj = block_flow->FirstChild(); obj;
       obj = obj->NextSibling()) {
    auto* child_block_flow = DynamicTo<LayoutBlockFlow>(obj);
    if (!child_block_flow)
      continue;
    if (!ShouldCheckLines(child_block_flow))
      continue;
    bool recursive_found = false;
    count +=
        LineCount(child_block_flow, stop_root_inline_box, &recursive_found);
    if (recursive_found) {
      if (found)
        *found = true;
      break;
    }
  }
  return count;
}

static void ClearTruncation(LayoutBlockFlow* block_flow) {
  if (block_flow->ChildrenInline() && block_flow->HasMarkupTruncation()) {
    block_flow->SetHasMarkupTruncation(false);
    for (RootInlineBox* box = block_flow->FirstRootBox(); box;
         box = box->NextRootBox())
      box->ClearTruncation();
    return;
  }
  for (LayoutObject* obj = block_flow->FirstChild(); obj;
       obj = obj->NextSibling()) {
    auto* child_block_flow = DynamicTo<LayoutBlockFlow>(obj);
    if (!child_block_flow)
      continue;
    if (ShouldCheckLines(child_block_flow))
      ClearTruncation(child_block_flow);
  }
}

LayoutDeprecatedFlexibleBox::LayoutDeprecatedFlexibleBox(Element* element)
    : LayoutBlock(element) {
  DCHECK(!ChildrenInline());
  if (!IsAnonymous()) {
    const KURL& url = GetDocument().Url();
    if (url.ProtocolIs("chrome")) {
      UseCounter::Count(GetDocument(), WebFeature::kDeprecatedFlexboxChrome);
    } else if (url.ProtocolIs("chrome-extension")) {
      UseCounter::Count(GetDocument(),
                        WebFeature::kDeprecatedFlexboxChromeExtension);
    } else {
      UseCounter::Count(GetDocument(),
                        WebFeature::kDeprecatedFlexboxWebContent);
    }
  }
}

LayoutDeprecatedFlexibleBox::~LayoutDeprecatedFlexibleBox() = default;

static LayoutUnit MarginWidthForChild(LayoutBox* child) {
  // A margin basically has three types: fixed, percentage, and auto (variable).
  // Auto and percentage margins simply become 0 when computing min/max width.
  // Fixed margins can be added in as is.
  const Length& margin_left = child->StyleRef().MarginLeft();
  const Length& margin_right = child->StyleRef().MarginRight();
  LayoutUnit margin;
  if (margin_left.IsFixed())
    margin += margin_left.Value();
  if (margin_right.IsFixed())
    margin += margin_right.Value();
  return margin;
}

static LayoutUnit HeightForChild(LayoutBox* child) {
  if (child->HasOverrideLogicalHeight())
    return child->OverrideLogicalHeight();
  return child->LogicalHeight();
}

static LayoutUnit ContentHeightForChild(LayoutBox* child) {
  // TODO(rego): Shouldn't we subtract the scrollbar height too?
  return (HeightForChild(child) - child->BorderAndPaddingLogicalHeight())
      .ClampNegativeToZero();
}

void LayoutDeprecatedFlexibleBox::StyleWillChange(
    StyleDifference diff,
    const ComputedStyle& new_style) {
  const ComputedStyle* old_style = Style();
  if (old_style && old_style->HasLineClamp() && !new_style.HasLineClamp())
    ClearLineClamp();

  LayoutBlock::StyleWillChange(diff, new_style);
}

MinMaxSizes LayoutDeprecatedFlexibleBox::ComputeIntrinsicLogicalWidths() const {
  MinMaxSizes sizes;
  for (LayoutBox* child = FirstChildBox(); child;
       child = child->NextSiblingBox()) {
    if (child->IsOutOfFlowPositioned())
      continue;

    MinMaxSizes child_sizes = child->PreferredLogicalWidths();
    child_sizes += MarginWidthForChild(child);

    sizes.Encompass(child_sizes);
  }

  sizes.max_size = std::max(sizes.min_size, sizes.max_size);
  sizes += BorderAndPaddingLogicalWidth() + ScrollbarLogicalWidth();
  return sizes;
}

void LayoutDeprecatedFlexibleBox::UpdateBlockLayout(bool relayout_children) {
  DCHECK(NeedsLayout());
  DCHECK_EQ(StyleRef().BoxOrient(), EBoxOrient::kVertical);

  UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxLayout);

  if (StyleRef().BoxAlign() != ComputedStyleInitialValues::InitialBoxAlign())
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxAlignNotInitial);

  if (StyleRef().BoxDirection() !=
      ComputedStyleInitialValues::InitialBoxDirection())
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxDirectionNotInitial);

  if (StyleRef().BoxPack() != ComputedStyleInitialValues::InitialBoxPack())
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxPackNotInitial);

  if (!FirstChildBox()) {
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxNoChildren);
  } else if (!FirstChildBox()->NextSiblingBox()) {
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxOneChild);

    auto* first_child_block_flow = DynamicTo<LayoutBlockFlow>(FirstChildBox());
    if (first_child_block_flow && first_child_block_flow->ChildrenInline()) {
      UseCounter::Count(GetDocument(),
                        WebFeature::kWebkitBoxOneChildIsLayoutBlockFlowInline);
    }
  } else {
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxManyChildren);
  }

  if (!relayout_children && SimplifiedLayout())
    return;

  {
    // LayoutState needs this deliberate scope to pop before paint invalidation.
    LayoutState state(*this);

    LayoutSize previous_size = Size();

    UpdateLogicalWidth();
    UpdateLogicalHeight();

    TextAutosizer::LayoutScope text_autosizer_layout_scope(this);

    if (previous_size != Size())
      relayout_children = true;

    SetHeight(LayoutUnit());

    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxLayoutVertical);
    LayoutVerticalBox(relayout_children);

    LayoutUnit old_client_after_edge = ClientLogicalBottom();
    UpdateLogicalHeight();

    if (previous_size.Height() != Size().Height())
      relayout_children = true;

    LayoutPositionedObjects(relayout_children || IsDocumentElement());

    ComputeLayoutOverflow(old_client_after_edge);
  }

  UpdateAfterLayout();

  ClearNeedsLayout();
}

// The first walk over our kids is to find out if we have any flexible children.
static void GatherFlexChildrenInfo(FlexBoxIterator& iterator,
                                   Document& document,
                                   bool relayout_children,
                                   bool& have_flex) {
  for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
    if (child->StyleRef().BoxFlex() !=
        ComputedStyleInitialValues::InitialBoxFlex())
      UseCounter::Count(document, WebFeature::kWebkitBoxChildFlexNotInitial);

    if (child->StyleRef().BoxOrdinalGroup() !=
        ComputedStyleInitialValues::InitialBoxOrdinalGroup()) {
      UseCounter::Count(document,
                        WebFeature::kWebkitBoxChildOrdinalGroupNotInitial);
    }

    // Check to see if this child flexes.
    if (!child->IsOutOfFlowPositioned() && child->StyleRef().BoxFlex() > 0.0f) {
      // We always have to lay out flexible objects again, since the flex
      // distribution
      // may have changed, and we need to reallocate space.
      child->ClearOverrideSize();
      if (!relayout_children)
        child->SetChildNeedsLayout(kMarkOnlyThis);
      have_flex = true;
    }
  }
}

void LayoutDeprecatedFlexibleBox::LayoutVerticalBox(bool relayout_children) {
  LayoutUnit y_pos = BorderTop() + PaddingTop();
  LayoutUnit to_add =
      BorderBottom() + PaddingBottom() + HorizontalScrollbarHeight();
  bool height_specified = false;
  bool paginated = View()->GetLayoutState()->IsPaginated();
  LayoutUnit old_height;

  LayoutUnit remaining_space;

  FlexBoxIterator iterator(this);
  bool have_flex = false, flexing_children = false;
  GatherFlexChildrenInfo(iterator, GetDocument(), relayout_children, have_flex);

  // We confine the line clamp ugliness to vertical flexible boxes (thus keeping
  // it out of
  // mainstream block layout); this is not really part of the XUL box model.
  if (StyleRef().HasLineClamp())
    ApplyLineClamp(iterator, relayout_children);

  PaintLayerScrollableArea::DelayScrollOffsetClampScope delay_clamp_scope;

  // We do 2 passes.  The first pass is simply to lay everyone out at
  // their preferred widths.  The second pass handles flexing the children.
  // Our first pass is done without flexing.  We simply lay the children
  // out within the box.
  do {
    SetHeight(BorderTop() + PaddingTop());
    LayoutUnit min_height = Size().Height() + to_add;

    for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
      if (child->IsOutOfFlowPositioned()) {
        child->ContainingBlock()->InsertPositionedObject(child);
        PaintLayer* child_layer = child->Layer();
        child_layer->SetStaticInlinePosition(BorderStart() + PaddingStart());
        if (child_layer->StaticBlockPosition() != Size().Height()) {
          child_layer->SetStaticBlockPosition(Size().Height());
          if (child->StyleRef().HasStaticBlockPosition(
                  StyleRef().IsHorizontalWritingMode()))
            child->SetChildNeedsLayout(kMarkOnlyThis);
        }
        continue;
      }

      SubtreeLayoutScope layout_scope(*child);
      if (!StyleRef().HasLineClamp() &&
          (relayout_children ||
           (child->IsAtomicInlineLevel() &&
            (child->StyleRef().Width().IsPercentOrCalc() ||
             child->StyleRef().Height().IsPercentOrCalc()))))
        layout_scope.SetChildNeedsLayout(child);

      // Compute the child's vertical margins.
      child->ComputeAndSetBlockDirectionMargins(this);

      // Add in the child's marginTop to our height.
      SetHeight(Size().Height() + child->MarginTop());

      if (!child->NeedsLayout())
        MarkChildForPaginationRelayoutIfNeeded(*child, layout_scope);

      // Now do a layout.
      child->LayoutIfNeeded();

      // We can place the child now, using our value of box-align.
      LayoutUnit child_x = BorderLeft() + PaddingLeft();
      switch (StyleRef().BoxAlign()) {
        case EBoxAlignment::kCenter:
        case EBoxAlignment::kBaseline:  // Baseline just maps to center for
                                        // vertical boxes
          child_x += child->MarginLeft() +
                     ((ContentWidth() -
                       (child->Size().Width() + child->MarginWidth())) /
                      2)
                         .ClampNegativeToZero();
          break;
        case EBoxAlignment::kEnd:
          if (!StyleRef().IsLeftToRightDirection()) {
            child_x += child->MarginLeft();
          } else {
            child_x +=
                ContentWidth() - child->MarginRight() - child->Size().Width();
          }
          break;
        default:  // BSTART/BSTRETCH
          if (StyleRef().IsLeftToRightDirection()) {
            child_x += child->MarginLeft();
          } else {
            child_x +=
                ContentWidth() - child->MarginRight() - child->Size().Width();
          }
          break;
      }

      // Place the child.
      PlaceChild(child, LayoutPoint(child_x, Size().Height()));
      SetHeight(Size().Height() + child->Size().Height() +
                child->MarginBottom());

      if (paginated)
        UpdateFragmentationInfoForChild(*child);
    }

    y_pos = Size().Height();

    if (!iterator.First() && HasLineIfEmpty()) {
      SetHeight(Size().Height() +
                LineHeight(true,
                           StyleRef().IsHorizontalWritingMode()
                               ? kHorizontalLine
                               : kVerticalLine,
                           kPositionOfInteriorLineBoxes));
    }

    SetHeight(Size().Height() + to_add);

    // Negative margins can cause our height to shrink below our minimal height
    // (border/padding).  If this happens, ensure that the computed height is
    // increased to the minimal height.
    if (Size().Height() < min_height)
      SetHeight(min_height);

    // Now we have to calc our height, so we know how much space we have
    // remaining.
    old_height = Size().Height();
    UpdateLogicalHeight();
    if (old_height != Size().Height())
      height_specified = true;

    remaining_space = Size().Height() - BorderBottom() - PaddingBottom() -
                      HorizontalScrollbarHeight() - y_pos;

    if (flexing_children) {
      have_flex = false;  // We're done.
    } else if (have_flex) {
      // We have some flexible objects.  See if we need to grow/shrink them at
      // all.
      if (!remaining_space)
        break;

      // Allocate the remaining space among the flexible objects.
      bool expanding = remaining_space > 0;
      do {
        // Flexing consists of multiple passes, since we have to change
        // ratios every time an object hits its max/min-width For a given
        // pass, we always start off by computing the totalFlex of all
        // objects that can grow/shrink at all, and computing the allowed
        // growth before an object hits its min/max width (and thus forces a
        // totalFlex recomputation).
        LayoutUnit remaining_space_at_beginning = remaining_space;
        float total_flex = 0.0f;
        for (LayoutBox* child = iterator.First(); child;
             child = iterator.Next()) {
          if (AllowedChildFlex(child, expanding))
            total_flex += child->StyleRef().BoxFlex();
        }
        LayoutUnit space_available_this_pass = remaining_space;
        for (LayoutBox* child = iterator.First(); child;
             child = iterator.Next()) {
          LayoutUnit allowed_flex = AllowedChildFlex(child, expanding);
          if (allowed_flex) {
            LayoutUnit projected_flex =
                (allowed_flex == LayoutUnit::Max())
                    ? allowed_flex
                    : static_cast<LayoutUnit>(
                          allowed_flex *
                          (total_flex / child->StyleRef().BoxFlex()));
            space_available_this_pass =
                expanding ? std::min(space_available_this_pass, projected_flex)
                          : std::max(space_available_this_pass, projected_flex);
          }
        }

        // If we can't grow/shrink anymore, break.
        if (!space_available_this_pass || total_flex == 0.0f)
          break;

        // Now distribute the space to objects.
        for (LayoutBox* child = iterator.First();
             child && space_available_this_pass && total_flex;
             child = iterator.Next()) {
          if (AllowedChildFlex(child, expanding)) {
            LayoutUnit space_add = static_cast<LayoutUnit>(
                space_available_this_pass *
                (child->StyleRef().BoxFlex() / total_flex));
            if (space_add) {
              child->SetOverrideLogicalHeight(HeightForChild(child) +
                                              space_add);
              flexing_children = true;
              relayout_children = true;
            }

            space_available_this_pass -= space_add;
            remaining_space -= space_add;

            total_flex -= child->StyleRef().BoxFlex();
          }
        }
        if (remaining_space == remaining_space_at_beginning) {
          // This is not advancing, avoid getting stuck by distributing the
          // remaining pixels.
          LayoutUnit space_add = LayoutUnit(remaining_space > 0 ? 1 : -1);
          for (LayoutBox* child = iterator.First(); child && remaining_space;
               child = iterator.Next()) {
            if (AllowedChildFlex(child, expanding)) {
              child->SetOverrideLogicalHeight(HeightForChild(child) +
                                              space_add);
              flexing_children = true;
              relayout_children = true;
              remaining_space -= space_add;
            }
          }
        }
      } while (AbsoluteValue(remaining_space) >= 1);

      // We didn't find any children that could grow.
      if (have_flex && !flexing_children)
        have_flex = false;
    }
  } while (have_flex);

  if (StyleRef().BoxPack() != EBoxPack::kStart && remaining_space > 0) {
    // Children must be repositioned.
    LayoutUnit offset;
    if (StyleRef().BoxPack() == EBoxPack::kJustify) {
      UseCounter::Count(GetDocument(),
                        WebFeature::kWebkitBoxPackJustifyDoesSomething);
      // Determine the total number of children.
      int total_children = 0;
      for (LayoutBox* child = iterator.First(); child;
           child = iterator.Next()) {
        if (child->IsOutOfFlowPositioned())
          continue;

        ++total_children;
      }

      // Iterate over the children and space them out according to the
      // justification level.
      if (total_children > 1) {
        --total_children;
        bool first_child = true;
        for (LayoutBox* child = iterator.First(); child;
             child = iterator.Next()) {
          if (child->IsOutOfFlowPositioned())
            continue;

          if (first_child) {
            first_child = false;
            continue;
          }

          offset += remaining_space / total_children;
          remaining_space -= (remaining_space / total_children);
          --total_children;
          PlaceChild(child,
                     child->Location() + LayoutSize(LayoutUnit(), offset));
        }
      }
    } else {
      if (StyleRef().BoxPack() == EBoxPack::kCenter) {
        UseCounter::Count(GetDocument(),
                          WebFeature::kWebkitBoxPackCenterDoesSomething);
        offset += remaining_space / 2;
      } else {  // END
        UseCounter::Count(GetDocument(),
                          WebFeature::kWebkitBoxPackEndDoesSomething);
        offset += remaining_space;
      }
      for (LayoutBox* child = iterator.First(); child;
           child = iterator.Next()) {
        if (child->IsOutOfFlowPositioned())
          continue;
        PlaceChild(child, child->Location() + LayoutSize(LayoutUnit(), offset));
      }
    }
  }

  // So that the computeLogicalHeight in layoutBlock() knows to relayout
  // positioned objects because of a height change, we revert our height back
  // to the intrinsic height before returning.
  if (height_specified)
    SetHeight(old_height);
}

void LayoutDeprecatedFlexibleBox::ApplyLineClamp(FlexBoxIterator& iterator,
                                                 bool relayout_children) {
  UseCounter::Count(GetDocument(), WebFeature::kLineClamp);
  UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxLineClamp);

  LayoutBox* child = FirstChildBox();
  if (!child) {
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxLineClampNoChildren);
  } else if (!child->NextSiblingBox()) {
    UseCounter::Count(GetDocument(), WebFeature::kWebkitBoxLineClampOneChild);

    auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
    if (child_block_flow && child_block_flow->ChildrenInline()) {
      UseCounter::Count(
          GetDocument(),
          WebFeature::kWebkitBoxLineClampOneChildIsLayoutBlockFlowInline);
    }
  } else {
    UseCounter::Count(GetDocument(),
                      WebFeature::kWebkitBoxLineClampManyChildren);
  }

  int max_line_count = 0;
  for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
    if (child->IsOutOfFlowPositioned())
      continue;

    child->ClearOverrideSize();
    if (relayout_children ||
        (child->IsAtomicInlineLevel() &&
         (child->StyleRef().Width().IsPercentOrCalc() ||
          child->StyleRef().Height().IsPercentOrCalc())) ||
        (child->StyleRef().Height().IsAuto() && child->IsLayoutBlock())) {
      child->SetChildNeedsLayout(kMarkOnlyThis);

      // Dirty all the positioned objects.
      auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
      if (child_block_flow) {
        child_block_flow->MarkPositionedObjectsForLayout();
        ClearTruncation(child_block_flow);
      }
    }
    child->LayoutIfNeeded();
    auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
    if (child->StyleRef().Height().IsAuto() && child_block_flow) {
      max_line_count = std::max(max_line_count, LineCount(child_block_flow));
    }
  }

  // Get the number of lines and then alter all block flow children with auto
  // height to use the
  // specified height. We always try to leave room for at least one line.
  int num_visible_lines = StyleRef().LineClamp();
  DCHECK_GT(num_visible_lines, 0);

  if (num_visible_lines >= max_line_count)
    return;

  for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
    auto* block_child = DynamicTo<LayoutBlockFlow>(child);
    if (child->IsOutOfFlowPositioned() ||
        !child->StyleRef().Height().IsAuto() || !block_child)
      continue;

    int line_count = blink::LineCount(block_child);
    if (line_count <= num_visible_lines)
      continue;

    int dummy_count = 0;
    LayoutUnit new_height(GetHeightForLineCount(block_child, num_visible_lines,
                                                true, dummy_count));
    if (new_height == child->Size().Height())
      continue;

    child->SetOverrideLogicalHeight(new_height);
    child->ForceLayout();

    // FIXME: For now don't support RTL.
    if (StyleRef().Direction() != TextDirection::kLtr)
      continue;

    // Get the last line
    RootInlineBox* last_line = LineAtIndex(block_child, line_count - 1);
    if (!last_line)
      continue;

    RootInlineBox* last_visible_line =
        LineAtIndex(block_child, num_visible_lines - 1);
    if (!last_visible_line)
      continue;

    DEFINE_STATIC_LOCAL(AtomicString, ellipsis_str,
                        (&kHorizontalEllipsisCharacter, 1));
    const Font& font = Style(num_visible_lines == 1)->GetFont();
    float total_width =
        font.Width(ConstructTextRun(font, &kHorizontalEllipsisCharacter, 1,
                                    StyleRef(), StyleRef().Direction()));

    // See if this width can be accommodated on the last visible line
    LineLayoutBlockFlow dest_block = last_visible_line->Block();
    LineLayoutBlockFlow src_block = last_line->Block();

    // FIXME: Directions of src/destBlock could be different from our direction
    // and from one another.
    if (!src_block.StyleRef().IsLeftToRightDirection())
      continue;

    bool left_to_right = dest_block.StyleRef().IsLeftToRightDirection();
    if (!left_to_right)
      continue;

    LayoutUnit block_right_edge = dest_block.LogicalRightOffsetForLine(
        last_visible_line->Y(), kDoNotIndentText);
    if (!last_visible_line->LineCanAccommodateEllipsis(
            left_to_right, block_right_edge,
            last_visible_line->X() + last_visible_line->LogicalWidth(),
            LayoutUnit(total_width)))
      continue;

    UseCounter::Count(GetDocument(),
                      WebFeature::kWebkitBoxLineClampDoesSomething);

    // Let the truncation code kick in.
    // FIXME: the text alignment should be recomputed after the width changes
    // due to truncation.
    LayoutUnit block_left_edge = dest_block.LogicalLeftOffsetForLine(
        last_visible_line->Y(), kDoNotIndentText);
    InlineBox* box_truncation_starts_at = nullptr;
    last_visible_line->PlaceEllipsis(ellipsis_str, left_to_right,
                                     block_left_edge, block_right_edge,
                                     LayoutUnit(total_width), LayoutUnit(),
                                     &box_truncation_starts_at, ForceEllipsis);
    dest_block.SetHasMarkupTruncation(true);
  }
}

void LayoutDeprecatedFlexibleBox::ClearLineClamp() {
  FlexBoxIterator iterator(this);
  for (LayoutBox* child = iterator.First(); child; child = iterator.Next()) {
    if (child->IsOutOfFlowPositioned())
      continue;

    child->ClearOverrideSize();
    if ((child->IsAtomicInlineLevel() &&
         (child->StyleRef().Width().IsPercentOrCalc() ||
          child->StyleRef().Height().IsPercentOrCalc())) ||
        (child->StyleRef().Height().IsAuto() && child->IsLayoutBlock())) {
      child->SetChildNeedsLayout();

      auto* child_block_flow = DynamicTo<LayoutBlockFlow>(child);
      if (child_block_flow) {
        child_block_flow->MarkPositionedObjectsForLayout();
        ClearTruncation(child_block_flow);
      }
    }
  }
}

void LayoutDeprecatedFlexibleBox::PlaceChild(LayoutBox* child,
                                             const LayoutPoint& location) {
  // FIXME Investigate if this can be removed based on other flags.
  // crbug.com/370010
  child->SetShouldCheckForPaintInvalidation();

  // Place the child.
  child->SetLocation(location);
}

LayoutUnit LayoutDeprecatedFlexibleBox::AllowedChildFlex(LayoutBox* child,
                                                         bool expanding) {
  if (child->IsOutOfFlowPositioned() || child->StyleRef().BoxFlex() == 0.0f)
    return LayoutUnit();

  if (expanding) {
    // FIXME: For now just handle fixed values.
    LayoutUnit max_height = LayoutUnit::Max();
    LayoutUnit height = ContentHeightForChild(child);
    if (child->StyleRef().MaxHeight().IsFixed())
      max_height = LayoutUnit(child->StyleRef().MaxHeight().Value());
    if (max_height == LayoutUnit::Max())
      return max_height;
    return (max_height - height).ClampNegativeToZero();
  }

  // FIXME: For now just handle fixed values.
  const Length& min_height_length = child->StyleRef().MinHeight();
  if (min_height_length.IsFixed() || min_height_length.IsAuto()) {
    LayoutUnit min_height(min_height_length.Value());
    LayoutUnit height = ContentHeightForChild(child);
    LayoutUnit allowed_shrinkage = (min_height - height).ClampPositiveToZero();
    return allowed_shrinkage;
  }
  return LayoutUnit();
}

}  // namespace blink
