/*
 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
 *               All right reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2013 Adobe Systems Incorporated.
 *
 * 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.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_BREAKING_CONTEXT_INLINE_HEADERS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_BREAKING_CONTEXT_INLINE_HEADERS_H_

#include "third_party/blink/renderer/core/layout/api/line_layout_box.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_list_marker.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_ruby_run.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_text.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_text_combine.h"
#include "third_party/blink/renderer/core/layout/line/inline_iterator.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/line/layout_text_info.h"
#include "third_party/blink/renderer/core/layout/line/line_breaker.h"
#include "third_party/blink/renderer/core/layout/line/line_info.h"
#include "third_party/blink/renderer/core/layout/line/line_width.h"
#include "third_party/blink/renderer/core/layout/line/trailing_objects.h"
#include "third_party/blink/renderer/core/layout/line/word_measurement.h"
#include "third_party/blink/renderer/core/layout/logical_values.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/platform/fonts/character_range.h"
#include "third_party/blink/renderer/platform/text/hyphenation.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

// We don't let our line box tree for a single line get any deeper than this.
const unsigned kCMaxLineDepth = 200;

class BreakingContext {
  STACK_ALLOCATED();

 public:
  BreakingContext(InlineBidiResolver& resolver,
                  LineInfo& in_line_info,
                  LineWidth& line_width,
                  LayoutTextInfo& in_layout_text_info,
                  bool applied_start_width,
                  LineLayoutBlockFlow block)
      : resolver_(resolver),
        current_(resolver.GetPosition()),
        line_break_(resolver.GetPosition()),
        block_(block),
        last_object_(current_.GetLineLayoutItem()),
        next_object_(nullptr),
        current_style_(nullptr),
        block_style_(block.Style()),
        line_info_(in_line_info),
        layout_text_info_(in_layout_text_info),
        width_(line_width),
        curr_ws_(EWhiteSpace::kNormal),
        last_ws_(EWhiteSpace::kNormal),
        preserves_newline_(false),
        at_start_(true),
        ignoring_spaces_(false),
        current_character_is_space_(false),
        applied_start_width_(applied_start_width),
        include_end_width_(true),
        auto_wrap_(false),
        auto_wrap_was_ever_true_on_line_(false),
        floats_fit_on_line_(true),
        collapse_white_space_(false),
        starting_new_paragraph_(line_info_.PreviousLineBrokeCleanly()),
        at_end_(false),
        line_midpoint_state_(resolver.GetMidpointState()) {
    line_info_.SetPreviousLineBrokeCleanly(false);
  }

  LineLayoutItem CurrentItem() { return current_.GetLineLayoutItem(); }
  InlineIterator LineBreak() { return line_break_; }
  bool AtEnd() { return at_end_; }

  void InitializeForCurrentObject();

  void Increment();

  void HandleBR(EClear&);
  void HandleOutOfFlowPositioned(Vector<LineLayoutBox>& positioned_objects);
  void HandleFloat();
  void HandleEmptyInline();
  void HandleReplaced();
  bool HandleText(WordMeasurements&, bool& hyphenated);
  void PrepareForNextCharacter(const LineLayoutText&,
                               bool& prohibit_break_inside,
                               bool previous_character_is_space);
  bool CanBreakAtWhitespace(bool break_words,
                            WordMeasurement&,
                            bool stopped_ignoring_spaces,
                            float char_width,
                            bool& hyphenated,
                            bool disable_soft_hyphen,
                            float& hyphen_width,
                            bool between_words,
                            bool mid_word_break,
                            bool can_break_mid_word,
                            bool previous_character_is_space,
                            float last_width_measurement,
                            const LineLayoutText&,
                            const Font&,
                            bool apply_word_spacing,
                            float word_spacing);
  bool TrailingSpaceExceedsAvailableWidth(bool can_break_mid_word,
                                          const LineLayoutText&,
                                          WordMeasurement&,
                                          bool apply_word_spacing,
                                          bool word_spacing,
                                          const Font&);
  WordMeasurement& CalculateWordWidth(WordMeasurements&,
                                      LineLayoutText&,
                                      unsigned last_space,
                                      float& last_width_measurement,
                                      float word_spacing_for_word_measurement,
                                      const Font&,
                                      float word_trailing_space_width,
                                      UChar);
  void StopIgnoringSpaces(unsigned& last_space);
  void CommitAndUpdateLineBreakIfNeeded();
  InlineIterator HandleEndOfLine();

  void ClearLineBreakIfFitsOnLine() {
    if (width_.FitsOnLine() || last_ws_ == EWhiteSpace::kNowrap)
      line_break_.Clear();
  }

 private:
  void SetCurrentCharacterIsSpace(UChar);
  void SkipTrailingWhitespace(InlineIterator&, const LineInfo&);
  bool ShouldMidWordBreak(UChar,
                          LineLayoutText,
                          const Font&,
                          unsigned& next_grapheme_cluster,
                          float& char_width,
                          float& width_from_last_breaking_opportunity,
                          bool break_all,
                          int& next_breakable_position_for_break_all);
  bool RewindToMidWordBreak(WordMeasurement&, int end, float width);
  bool CanMidWordBreakBefore(LineLayoutText);
  bool RewindToFirstMidWordBreak(LineLayoutText,
                                 const ComputedStyle&,
                                 const Font&,
                                 const LazyLineBreakIterator&,
                                 WordMeasurement&);
  bool RewindToMidWordBreak(LineLayoutText,
                            const ComputedStyle&,
                            const Font&,
                            bool break_all,
                            WordMeasurement&);
  bool Hyphenate(LineLayoutText,
                 const ComputedStyle&,
                 const Font&,
                 const Hyphenation&,
                 float last_space_word_spacing,
                 WordMeasurement&);
  bool IsBreakAtSoftHyphen() const;

  InlineBidiResolver& resolver_;

  InlineIterator current_;
  InlineIterator line_break_;
  InlineIterator start_of_ignored_spaces_;

  LineLayoutBlockFlow block_;
  LineLayoutItem last_object_;
  LineLayoutItem next_object_;

  const ComputedStyle* current_style_;
  const ComputedStyle* block_style_;

  LineInfo& line_info_;

  LayoutTextInfo& layout_text_info_;

  LineWidth width_;

  EWhiteSpace curr_ws_;
  EWhiteSpace last_ws_;

  bool preserves_newline_;
  bool at_start_;
  bool ignoring_spaces_;
  bool current_character_is_space_;
  bool single_leading_space_;
  unsigned current_start_offset_;  // initial offset for the current text
  bool applied_start_width_;
  bool include_end_width_;
  bool auto_wrap_;
  bool auto_wrap_was_ever_true_on_line_;
  bool floats_fit_on_line_;
  bool collapse_white_space_;
  bool starting_new_paragraph_;
  bool at_end_;

  LineMidpointState& line_midpoint_state_;

  TrailingObjects trailing_objects_;
};

// When ignoring spaces, this needs to be called for objects that need line
// boxes such as LayoutInlines or hard line breaks to ensure that they're not
// ignored.
inline void EnsureLineBoxInsideIgnoredSpaces(LineMidpointState* midpoint_state,
                                             LineLayoutItem item) {
  InlineIterator midpoint(nullptr, item, 0);
  midpoint_state->StopIgnoringSpaces(midpoint);
  midpoint_state->StartIgnoringSpaces(midpoint);
}

inline bool ShouldCollapseWhiteSpace(const ComputedStyle& style,
                                     const LineInfo& line_info,
                                     WhitespacePosition whitespace_position) {
  // CSS2 16.6.1
  // If a space (U+0020) at the beginning of a line has 'white-space' set to
  // 'normal', 'nowrap', or 'pre-line', it is removed.
  // If a space (U+0020) at the end of a line has 'white-space' set to 'normal',
  // 'nowrap', or 'pre-line', it is also removed.
  // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space'
  // set to 'pre-wrap', UAs may visually collapse them.
  return style.CollapseWhiteSpace() ||
         (whitespace_position == kTrailingWhitespace &&
          style.WhiteSpace() == EWhiteSpace::kPreWrap &&
          (!line_info.IsEmpty() || !line_info.PreviousLineBrokeCleanly()));
}

inline bool RequiresLineBoxForContent(LineLayoutInline flow,
                                      const LineInfo& line_info) {
  LineLayoutItem parent = flow.Parent();
  if (flow.GetDocument().InNoQuirksMode() &&
      (flow.Style(line_info.IsFirstLine())->LineHeight() !=
           parent.Style(line_info.IsFirstLine())->LineHeight() ||
       flow.StyleRef().VerticalAlign() != parent.StyleRef().VerticalAlign() ||
       !parent.StyleRef().HasIdenticalAscentDescentAndLineGap(flow.StyleRef())))
    return true;
  return false;
}

inline bool AlwaysRequiresLineBox(LineLayoutItem flow) {
  // FIXME: Right now, we only allow line boxes for inlines that are truly
  // empty. We need to fix this, though, because at the very least, inlines
  // containing only ignorable whitespace should should also have line boxes.
  return IsEmptyInline(flow) &&
         LineLayoutInline(flow).HasInlineDirectionBordersPaddingOrMargin();
}

inline bool RequiresLineBox(
    const InlineIterator& it,
    const LineInfo& line_info = LineInfo(),
    WhitespacePosition whitespace_position = kLeadingWhitespace) {
  if (it.GetLineLayoutItem().IsEmptyText())
    return false;

  if (it.GetLineLayoutItem().IsFloatingOrOutOfFlowPositioned())
    return false;

  if (it.GetLineLayoutItem().IsLayoutInline() &&
      !AlwaysRequiresLineBox(it.GetLineLayoutItem()) &&
      !RequiresLineBoxForContent(LineLayoutInline(it.GetLineLayoutItem()),
                                 line_info))
    return false;

  if (!ShouldCollapseWhiteSpace(it.GetLineLayoutItem().StyleRef(), line_info,
                                whitespace_position) ||
      it.GetLineLayoutItem().IsBR())
    return true;

  UChar current = it.Current();
  bool not_just_whitespace = current != kSpaceCharacter &&
                             current != kTabulationCharacter &&
                             current != kSoftHyphenCharacter &&
                             (current != kNewlineCharacter ||
                              it.GetLineLayoutItem().PreservesNewline());
  return not_just_whitespace || IsEmptyInline(it.GetLineLayoutItem());
}

inline void SetStaticPositions(LineLayoutBlockFlow block,
                               LineLayoutBox child,
                               IndentTextOrNot indent_text) {
  DCHECK(child.IsOutOfFlowPositioned());
  // FIXME: The math here is actually not really right. It's a best-guess
  // approximation that will work for the common cases
  LineLayoutItem container_block = child.Container();
  LayoutUnit block_height = block.LogicalHeight();
  if (container_block.IsLayoutInline()) {
    // A relative positioned inline encloses us. In this case, we also have to
    // determine our position as though we were an inline.
    // Set |staticInlinePosition| and |staticBlockPosition| on the relative
    // positioned inline so that we can obtain the value later.
    LineLayoutInline(container_block)
        .Layer()
        ->SetStaticInlinePosition(
            block.StartAlignedOffsetForLine(block_height, indent_text));
    LineLayoutInline(container_block)
        .Layer()
        ->SetStaticBlockPosition(block_height);

    // If |child| is a leading or trailing positioned object this is its only
    // opportunity to ensure it moves with an inline container changing width.
    child.MoveWithEdgeOfInlineContainerIfNecessary(
        child.IsHorizontalWritingMode());
  }
  block.UpdateStaticInlinePositionForChild(child, block_height, indent_text);
  child.Layer()->SetStaticBlockPosition(block_height);
}

// FIXME: The entire concept of the skipTrailingWhitespace function is flawed,
// since we really need to be building line boxes even for containers that may
// ultimately collapse away. Otherwise we'll never get positioned elements quite
// right. In other words, we need to build this function's work into the normal
// line object iteration process. NB. this function will insert any floating
// elements that would otherwise be skipped but it will not position them.
inline void BreakingContext::SkipTrailingWhitespace(InlineIterator& iterator,
                                                    const LineInfo& line_info) {
  while (!iterator.AtEnd() &&
         !RequiresLineBox(iterator, line_info, kTrailingWhitespace)) {
    LineLayoutItem item = iterator.GetLineLayoutItem();
    if (item.IsOutOfFlowPositioned())
      SetStaticPositions(block_, LineLayoutBox(item), kDoNotIndentText);
    else if (item.IsFloating())
      block_.InsertFloatingObject(LineLayoutBox(item));
    iterator.Increment();
  }
}

inline void BreakingContext::InitializeForCurrentObject() {
  current_style_ = current_.GetLineLayoutItem().Style();
  next_object_ =
      BidiNextSkippingEmptyInlines(block_, current_.GetLineLayoutItem());
  if (next_object_ && next_object_.Parent() &&
      !next_object_.Parent().IsDescendantOf(
          current_.GetLineLayoutItem().Parent()))
    include_end_width_ = true;

  curr_ws_ =
      current_.GetLineLayoutItem().IsLayoutInline()
          ? current_style_->WhiteSpace()
          : current_.GetLineLayoutItem().Parent().StyleRef().WhiteSpace();
  last_ws_ = last_object_.IsLayoutInline()
                 ? last_object_.StyleRef().WhiteSpace()
                 : last_object_.Parent().StyleRef().WhiteSpace();

  bool is_svg_text = current_.GetLineLayoutItem().IsSVGInlineText();
  auto_wrap_ = !is_svg_text && ComputedStyle::AutoWrap(curr_ws_);
  auto_wrap_was_ever_true_on_line_ =
      auto_wrap_was_ever_true_on_line_ || auto_wrap_;

  preserves_newline_ = !is_svg_text && ComputedStyle::PreserveNewline(curr_ws_);

  collapse_white_space_ = ComputedStyle::CollapseWhiteSpace(curr_ws_);

  // Ensure the whitespace in constructions like '<span style="white-space:
  // pre-wrap">text <span><span> text</span>' does not collapse.
  if (collapse_white_space_ && !ComputedStyle::CollapseWhiteSpace(last_ws_))
    current_character_is_space_ = false;

  // Since current_ iterates all along the text's length, we need to store the
  // initial offset of the current handle text so that we can then identify
  // a single leading white-space as potential breaking opportunities.
  current_start_offset_ = current_.Offset();
  single_leading_space_ = false;
}

inline void BreakingContext::Increment() {
  current_.MoveToStartOf(next_object_);

  // When the line box tree is created, this position in the line will be
  // snapped to LayoutUnit's, and those measurements will be used by the paint
  // code. Do the equivalent snapping here, to get consistent line measurements.
  width_.SnapAtNodeBoundary();

  at_start_ = false;
}

inline void BreakingContext::HandleBR(EClear& clear) {
  if (width_.FitsOnLine()) {
    LineLayoutItem br = current_.GetLineLayoutItem();
    line_break_.MoveToStartOf(br);
    line_break_.Increment();

    // A <br> always breaks a line, so don't let the line be collapsed
    // away. Also, the space at the end of a line with a <br> does not
    // get collapsed away. It only does this if the previous line broke
    // cleanly. Otherwise the <br> has no effect on whether the line is
    // empty or not.
    if (starting_new_paragraph_)
      line_info_.SetEmpty(false);
    trailing_objects_.Clear();
    line_info_.SetPreviousLineBrokeCleanly(true);

    // A <br> with clearance always needs a linebox in case the lines below it
    // get dirtied later and need to check for floats to clear - so if we're
    // ignoring spaces, stop ignoring them and add a run for this object.
    if (ignoring_spaces_ && current_style_->Clear() != EClear::kNone)
      EnsureLineBoxInsideIgnoredSpaces(&line_midpoint_state_, br);

    if (!line_info_.IsEmpty())
      clear = ResolvedClear(*current_style_, block_.StyleRef());
  }
  at_end_ = true;
}

inline LayoutUnit BorderPaddingMarginStart(LineLayoutInline child) {
  return child.MarginStart() + child.PaddingStart() + child.BorderStart();
}

inline LayoutUnit BorderPaddingMarginEnd(LineLayoutInline child) {
  return child.MarginEnd() + child.PaddingEnd() + child.BorderEnd();
}

enum CollapsibleWhiteSpace {
  IgnoreCollapsibleWhiteSpace,
  UseCollapsibleWhiteSpace
};

inline bool ShouldAddBorderPaddingMargin(LineLayoutItem child,
                                         bool& check_side,
                                         CollapsibleWhiteSpace white_space) {
  if (!child)
    return true;
  if (child.IsText()) {
    // A caller will only be interested in adding BPM from objects separated by
    // collapsible whitespace if they haven't already been added to the line's
    // width, such as when adding end-BPM when about to place a float after a
    // linebox.
    if (white_space == UseCollapsibleWhiteSpace &&
        LineLayoutText(child).IsAllCollapsibleWhitespace())
      return true;
    if (!LineLayoutText(child).TextLength())
      return true;
  }
  check_side = false;
  return check_side;
}

inline LayoutUnit InlineLogicalWidthFromAncestorsIfNeeded(
    LineLayoutItem child,
    bool start = true,
    bool end = true,
    CollapsibleWhiteSpace white_space = IgnoreCollapsibleWhiteSpace) {
  unsigned line_depth = 1;
  LayoutUnit extra_width;
  LineLayoutItem parent = child.Parent();
  while (parent.IsLayoutInline() && line_depth++ < kCMaxLineDepth) {
    LineLayoutInline parent_as_layout_inline(parent);
    if (!IsEmptyInline(parent_as_layout_inline)) {
      if (start && ShouldAddBorderPaddingMargin(child.PreviousSibling(), start,
                                                white_space))
        extra_width += BorderPaddingMarginStart(parent_as_layout_inline);
      if (end &&
          ShouldAddBorderPaddingMargin(child.NextSibling(), end, white_space))
        extra_width += BorderPaddingMarginEnd(parent_as_layout_inline);
      if (!start && !end)
        return extra_width;
    }
    child = parent;
    parent = child.Parent();
  }
  return extra_width;
}

inline void BreakingContext::HandleOutOfFlowPositioned(
    Vector<LineLayoutBox>& positioned_objects) {
  // If our original display wasn't an inline type, then we can
  // go ahead and determine our static inline position now.
  LineLayoutBox box(current_.GetLineLayoutItem());
  bool is_inline_type = box.StyleRef().IsOriginalDisplayInlineType();
  if (!is_inline_type) {
    block_.SetStaticInlinePositionForChild(box, block_.StartOffsetForContent());
  } else {
    // If our original display was an INLINE type, then we can determine our
    // static y position now. Note, however, that if we're paginated, we may
    // have to update this position after the line has been laid out, since the
    // line may be pushed by a pagination strut.
    box.Layer()->SetStaticBlockPosition(block_.LogicalHeight());
  }

  // If we're ignoring spaces, we have to stop and include this object and
  // then start ignoring spaces again.
  bool container_is_inline = box.Container().IsLayoutInline();
  if (is_inline_type || container_is_inline) {
    if (ignoring_spaces_)
      EnsureLineBoxInsideIgnoredSpaces(&line_midpoint_state_, box);
    trailing_objects_.AppendObjectIfNeeded(box);
  }
  if (!container_is_inline)
    positioned_objects.push_back(box);
  width_.AddUncommittedWidth(
      InlineLogicalWidthFromAncestorsIfNeeded(box).ToFloat());
  // Reset prior line break context characters.
  layout_text_info_.line_break_iterator_.ResetPriorContext();
}

inline void BreakingContext::HandleFloat() {
  LineLayoutBox float_box(current_.GetLineLayoutItem());
  FloatingObject* floating_object = block_.InsertFloatingObject(float_box);

  if (floats_fit_on_line_) {
    // We need to calculate the logical width of the float before we can tell
    // whether it's going to fit on the line. That means that we need to
    // position and lay it out. Note that we have to avoid positioning floats
    // that have been placed prematurely: Sometimes, floats are inserted too
    // early by skipTrailingWhitespace(), and later on they all get placed by
    // the first float here in handleFloat(). Their position may then be wrong,
    // but it's too late to do anything about that now. See crbug.com/671577
    if (!floating_object->IsPlaced())
      block_.PositionAndLayoutFloat(*floating_object, block_.LogicalHeight());

    // Check if it fits in the current line; if it does, place it now,
    // otherwise, place it after moving to next line (in newLine() func).
    // FIXME: Bug 110372: Properly position multiple stacked floats with
    // non-rectangular shape outside.
    // When fitting the float on the line we need to treat the width on the line
    // so far as though end-border, -padding and -margin from
    // inline ancestors has been applied to the end of the previous inline box.
    float width_from_ancestors =
        InlineLogicalWidthFromAncestorsIfNeeded(float_box, false, true,
                                                UseCollapsibleWhiteSpace)
            .ToFloat();
    width_.AddUncommittedWidth(width_from_ancestors);
    if (width_.FitsOnLine(
            block_.LogicalWidthForFloat(*floating_object).ToFloat(),
            kExcludeWhitespace)) {
      block_.PlaceNewFloats(block_.LogicalHeight(), &width_);
      if (line_break_.GetLineLayoutItem() == current_.GetLineLayoutItem()) {
        DCHECK(!line_break_.Offset());
        line_break_.Increment();
      }
    } else {
      floats_fit_on_line_ = false;
    }
    width_.AddUncommittedWidth(-width_from_ancestors);
  }
  // Update prior line break context characters, using U+FFFD (OBJECT
  // REPLACEMENT CHARACTER) for floating element.
  layout_text_info_.line_break_iterator_.UpdatePriorContext(
      kReplacementCharacter);
}

// This is currently just used for list markers and inline flows that have line
// boxes. Neither should have an effect on whitespace at the start of the line.
inline bool ShouldSkipWhitespaceAfterStartObject(
    LineLayoutBlockFlow block,
    LineLayoutItem o,
    LineMidpointState& line_midpoint_state) {
  LineLayoutItem next = BidiNextSkippingEmptyInlines(block, o);
  while (next && next.IsFloatingOrOutOfFlowPositioned())
    next = BidiNextSkippingEmptyInlines(block, next);

  while (next && IsEmptyInline(next)) {
    LineLayoutItem child = LineLayoutInline(next).FirstChild();
    next = child ? child : BidiNextSkippingEmptyInlines(block, next);
  }

  if (next && !next.IsBR() && next.IsText() &&
      LineLayoutText(next).TextLength() > 0) {
    LineLayoutText next_text(next);
    UChar next_char = next_text.CharacterAt(0);
    if (next_text.StyleRef().IsCollapsibleWhiteSpace(next_char)) {
      line_midpoint_state.StartIgnoringSpaces(InlineIterator(nullptr, o, 0));
      return true;
    }
  }

  return false;
}

inline void BreakingContext::HandleEmptyInline() {
  // This should only end up being called on empty inlines
  DCHECK(current_.GetLineLayoutItem());

  LineLayoutInline flow_box(current_.GetLineLayoutItem());

  bool requires_line_box = AlwaysRequiresLineBox(current_.GetLineLayoutItem());
  if (requires_line_box || RequiresLineBoxForContent(flow_box, line_info_)) {
    // An empty inline that only has line-height, vertical-align or font-metrics
    // will not force linebox creation (and thus affect the height of the line)
    // if the rest of the line is empty.
    if (requires_line_box)
      line_info_.SetEmpty(false);
    if (ignoring_spaces_) {
      // If we are in a run of ignored spaces then ensure we get a linebox if
      // lineboxes are eventually created for the line...
      trailing_objects_.Clear();
      EnsureLineBoxInsideIgnoredSpaces(&line_midpoint_state_,
                                       current_.GetLineLayoutItem());
    } else if (block_style_->CollapseWhiteSpace() &&
               resolver_.GetPosition().GetLineLayoutItem() ==
                   current_.GetLineLayoutItem() &&
               ShouldSkipWhitespaceAfterStartObject(
                   block_, current_.GetLineLayoutItem(),
                   line_midpoint_state_)) {
      // If this object is at the start of the line, we need to behave like list
      // markers and start ignoring spaces.
      current_character_is_space_ = true;
      ignoring_spaces_ = true;
    } else {
      // If we are after a trailing space but aren't ignoring spaces yet then
      // ensure we get a linebox if we encounter collapsible whitepace.
      trailing_objects_.AppendObjectIfNeeded(current_.GetLineLayoutItem());
    }
  }

  width_.AddUncommittedWidth(
      (InlineLogicalWidthFromAncestorsIfNeeded(current_.GetLineLayoutItem()) +
       BorderPaddingMarginStart(flow_box) + BorderPaddingMarginEnd(flow_box))
          .ToFloat());
}

inline void BreakingContext::HandleReplaced() {
  LineLayoutBox replaced_box(current_.GetLineLayoutItem());

  if (at_start_)
    width_.UpdateAvailableWidth(replaced_box.LogicalHeight());

  // Break on replaced elements if either has normal white-space,
  // or if the replaced element is ruby that can break before.
  if ((auto_wrap_ || ComputedStyle::AutoWrap(last_ws_)) &&
      (!current_.GetLineLayoutItem().IsRubyRun() ||
       LineLayoutRubyRun(current_.GetLineLayoutItem())
           .CanBreakBefore(layout_text_info_.line_break_iterator_))) {
    width_.Commit();
    line_break_.MoveToStartOf(current_.GetLineLayoutItem());
  }

  if (ignoring_spaces_) {
    line_midpoint_state_.StopIgnoringSpaces(
        InlineIterator(nullptr, current_.GetLineLayoutItem(), 0));
  }
  line_info_.SetEmpty(false);
  ignoring_spaces_ = false;
  current_character_is_space_ = false;
  trailing_objects_.Clear();

  // Optimize for a common case. If we can't find whitespace after the list
  // item, then this is all moot.
  LayoutUnit replaced_logical_width =
      block_.LogicalWidthForChild(replaced_box) +
      block_.MarginStartForChild(replaced_box) +
      block_.MarginEndForChild(replaced_box) +
      InlineLogicalWidthFromAncestorsIfNeeded(current_.GetLineLayoutItem());
  if (current_.GetLineLayoutItem().IsListMarker()) {
    if (block_style_->CollapseWhiteSpace() &&
        ShouldSkipWhitespaceAfterStartObject(
            block_, current_.GetLineLayoutItem(), line_midpoint_state_)) {
      // Like with inline flows, we start ignoring spaces to make sure that any
      // additional spaces we see will be discarded.
      current_character_is_space_ = true;
      ignoring_spaces_ = true;
    }
    if (LineLayoutListMarker(current_.GetLineLayoutItem()).IsInside())
      width_.AddUncommittedWidth(replaced_logical_width.ToFloat());
  } else {
    width_.AddUncommittedWidth(replaced_logical_width.ToFloat());
  }
  if (current_.GetLineLayoutItem().IsRubyRun())
    width_.ApplyOverhang(LineLayoutRubyRun(current_.GetLineLayoutItem()),
                         last_object_, next_object_);
  // Update prior line break context characters, using U+FFFD (OBJECT
  // REPLACEMENT CHARACTER) for replaced element.
  layout_text_info_.line_break_iterator_.UpdatePriorContext(
      kReplacementCharacter);
}

inline void NextCharacter(UChar& current_character,
                          UChar& last_character,
                          UChar& second_to_last_character) {
  second_to_last_character = last_character;
  last_character = current_character;
}

ALWAYS_INLINE void BreakingContext::SetCurrentCharacterIsSpace(UChar c) {
  current_character_is_space_ =
      c == kSpaceCharacter || c == kTabulationCharacter ||
      (!preserves_newline_ && (c == kNewlineCharacter));
}

inline float FirstPositiveWidth(const WordMeasurements& word_measurements) {
  for (const WordMeasurement& word_measurement : word_measurements) {
    if (word_measurement.width > 0)
      return word_measurement.width;
  }
  return 0;
}

ALWAYS_INLINE TextDirection
TextDirectionFromUnicode(WTF::unicode::CharDirection direction) {
  return direction == WTF::unicode::kRightToLeft ||
                 direction == WTF::unicode::kRightToLeftArabic
             ? TextDirection::kRtl
             : TextDirection::kLtr;
}

ALWAYS_INLINE float TextWidth(
    LineLayoutText text,
    unsigned from,
    unsigned len,
    const Font& font,
    float x_pos,
    bool collapse_white_space,
    HashSet<const SimpleFontData*>* fallback_fonts = nullptr,
    FloatRect* glyph_bounds = nullptr) {
  if ((!from && len == text.TextLength()) || text.StyleRef().HasTextCombine()) {
    return text.Width(from, len, font, LayoutUnit(x_pos),
                      text.StyleRef().Direction(), fallback_fonts,
                      glyph_bounds);
  }

  TextRun run = ConstructTextRun(font, text, from, len, text.StyleRef());
  run.SetTabSize(!collapse_white_space, text.StyleRef().GetTabSize());
  run.SetXPos(x_pos);
  return font.Width(run, fallback_fonts, glyph_bounds);
}

ALWAYS_INLINE bool BreakingContext::ShouldMidWordBreak(
    UChar c,
    LineLayoutText layout_text,
    const Font& font,
    unsigned& next_grapheme_cluster,
    float& char_width,
    float& width_from_last_breaking_opportunity,
    bool break_all,
    int& next_breakable_position_for_break_all) {
  // For breakWords/breakAll, we need to measure up to normal break
  // opportunity and then rewindToMidWordBreak() because ligatures/kerning can
  // shorten the width as we add more characters.
  // However, doing so can hit the performance when a "word" is really long,
  // such as minimized JS, because the next line will re-shape the rest of the
  // word in the current architecture.
  // This function is a heuristic optimization to stop at 2em overflow.
  float overflow_allowance = 2 * font.GetFontDescription().ComputedSize();

  width_from_last_breaking_opportunity += char_width;
  unsigned char_len;
  if (layout_text.Is8Bit()) {
    // For 8-bit string, code unit == grapheme cluster.
    char_len = 1;
  } else {
    NonSharedCharacterBreakIterator iterator(layout_text.GetText());
    int next = iterator.Following(current_.Offset());
    next_grapheme_cluster =
        next != kTextBreakDone ? next : layout_text.TextLength();
    char_len = next_grapheme_cluster - current_.Offset();
  }
  char_width =
      TextWidth(layout_text, current_.Offset(), char_len, font,
                width_.CommittedWidth() + width_from_last_breaking_opportunity,
                collapse_white_space_);
  if (width_.CommittedWidth() + width_from_last_breaking_opportunity +
          char_width <=
      width_.AvailableWidth() + overflow_allowance)
    return false;

  // breakAll has different break opportunities. Ensure we break only at
  // breakAll allows to break.
  if (break_all && !layout_text_info_.line_break_iterator_.IsBreakable(
                       current_.Offset(), next_breakable_position_for_break_all,
                       LineBreakType::kBreakAll)) {
    return false;
  }

  return true;
}

ALWAYS_INLINE bool BreakingContext::RewindToMidWordBreak(
    WordMeasurement& word_measurement,
    int end,
    float width) {
  word_measurement.end_offset = end;
  word_measurement.width = width;

  current_.MoveTo(current_.GetLineLayoutItem(), end,
                  current_.NextBreakablePosition());
  SetCurrentCharacterIsSpace(current_.Current());
  line_break_.MoveTo(current_.GetLineLayoutItem(), end,
                     current_.NextBreakablePosition());
  return true;
}

ALWAYS_INLINE bool BreakingContext::CanMidWordBreakBefore(LineLayoutText text) {
  // No break opportunities at the beginning of a line.
  if (!width_.CurrentWidth())
    return false;
  // If this text node is not the first child of an inline, the parent and the
  // preivous have the same style.
  if (text.PreviousSibling())
    return true;
  // Element boundaries belong to the parent of the element.
  // TODO(kojii): Not all cases of element boundaries are supported yet.
  // crbug.com/282134
  if (LineLayoutItem element = text.Parent()) {
    if (LineLayoutItem parent = element.Parent()) {
      const ComputedStyle& parent_style = parent.StyleRef();
      return parent_style.AutoWrap() &&
             ((parent_style.BreakWords() && !width_.CommittedWidth()) ||
              parent_style.WordBreak() == EWordBreak::kBreakAll);
    }
  }
  return false;
}

ALWAYS_INLINE bool BreakingContext::RewindToFirstMidWordBreak(
    LineLayoutText text,
    const ComputedStyle& style,
    const Font& font,
    const LazyLineBreakIterator& break_iterator,
    WordMeasurement& word_measurement) {
  int start = word_measurement.start_offset;
  int end = CanMidWordBreakBefore(text)
                ? start
                : break_iterator.NextBreakOpportunity(start + 1);
  if (end >= word_measurement.end_offset)
    return false;

  float width = TextWidth(text, start, end - start, font, width_.CurrentWidth(),
                          collapse_white_space_);
  // If the first break opportunity doesn't fit, and if there's a break
  // opportunity in previous runs, break at the opportunity.
  if (!width_.FitsOnLine(width) &&
      (width_.CommittedWidth() || single_leading_space_))
    return false;
  return RewindToMidWordBreak(word_measurement, end, width);
}

ALWAYS_INLINE bool BreakingContext::RewindToMidWordBreak(
    LineLayoutText text,
    const ComputedStyle& style,
    const Font& font,
    bool break_all,
    WordMeasurement& word_measurement) {
  int start = word_measurement.start_offset;
  int len = word_measurement.end_offset - start;
  if (!len)
    return false;

  LazyLineBreakIterator break_iterator(
      text.GetText(), style.LocaleForLineBreakIterator(),
      break_all ? LineBreakType::kBreakAll : LineBreakType::kBreakCharacter);
  float x_pos_to_break = width_.AvailableWidth() - width_.CurrentWidth();
  if (x_pos_to_break <= LayoutUnit::Epsilon()) {
    // There were no space left. Skip computing how many characters can fit.
    return RewindToFirstMidWordBreak(text, style, font, break_iterator,
                                     word_measurement);
  }

  TextRun run = ConstructTextRun(font, text, start, len, style);
  run.SetTabSize(!collapse_white_space_, style.GetTabSize());
  run.SetXPos(width_.CurrentWidth());

  // TODO(kojii): should be replaced with safe-to-break when hb is ready.
  x_pos_to_break += LayoutUnit::Epsilon();
  if (run.Rtl())
    x_pos_to_break = word_measurement.width - x_pos_to_break;
  len = font.OffsetForPosition(run, x_pos_to_break, OnlyFullGlyphs,
                               DontBreakGlyphs);
  int end = start + len;
  if (len) {
    end = break_iterator.PreviousBreakOpportunity(end, start);
    len = end - start;
  }
  if (!len) {
    // No characters can fit in the available space.
    // Break at the first mid-word break opportunity and let the line overflow.
    return RewindToFirstMidWordBreak(text, style, font, break_iterator,
                                     word_measurement);
  }

  FloatRect rect = font.SelectionRectForText(run, FloatPoint(), 0, 0, len);
  return RewindToMidWordBreak(word_measurement, end, rect.Width());
}

ALWAYS_INLINE bool BreakingContext::Hyphenate(
    LineLayoutText text,
    const ComputedStyle& style,
    const Font& font,
    const Hyphenation& hyphenation,
    float last_space_word_spacing,
    WordMeasurement& word_measurement) {
  unsigned start = word_measurement.start_offset;
  unsigned len = word_measurement.end_offset - start;
  if (len <= Hyphenation::kMinimumSuffixLength)
    return false;

  float hyphen_width = text.HyphenWidth(
      font, TextDirectionFromUnicode(resolver_.GetPosition().Direction()));
  float max_prefix_width = width_.AvailableWidth() - width_.CurrentWidth() -
                           hyphen_width - last_space_word_spacing;

  if (max_prefix_width <=
      font.GetFontDescription().MinimumPrefixWidthToHyphenate()) {
    return false;
  }

  TextRun run = ConstructTextRun(font, text, start, len, style);
  run.SetTabSize(!collapse_white_space_, style.GetTabSize());
  run.SetXPos(width_.CurrentWidth());
  // TODO(fserb): Check if this need to be BreakGlyphs.
  unsigned max_prefix_length = font.OffsetForPosition(
      run, max_prefix_width, OnlyFullGlyphs, DontBreakGlyphs);
  if (max_prefix_length < Hyphenation::kMinimumPrefixLength)
    return false;

  unsigned prefix_length = hyphenation.LastHyphenLocation(
      StringView(text.GetText(), start, len),
      std::min(max_prefix_length, len - Hyphenation::kMinimumSuffixLength) + 1);
  DCHECK_LE(prefix_length, max_prefix_length);
  if (!prefix_length || prefix_length < Hyphenation::kMinimumPrefixLength)
    return false;

  // TODO(kojii): getCharacterRange() measures as if the word were not broken
  // as defined in the spec, and is faster than measuring each fragment, but
  // ignores the kerning between the last letter and the hyphen.
  return RewindToMidWordBreak(
      word_measurement, start + prefix_length,
      font.GetCharacterRange(run, 0, prefix_length).Width());
}

ALWAYS_INLINE bool BreakingContext::IsBreakAtSoftHyphen() const {
  return line_break_ != resolver_.GetPosition()
             ? line_break_.PreviousInSameNode() == kSoftHyphenCharacter
             : current_.PreviousInSameNode() == kSoftHyphenCharacter;
}

static ALWAYS_INLINE bool HasVisibleText(LineLayoutText layout_text,
                                         unsigned offset) {
  return !layout_text.ContainsOnlyWhitespace(offset,
                                             layout_text.TextLength() - offset);
}

inline bool BreakingContext::HandleText(WordMeasurements& word_measurements,
                                        bool& hyphenated) {
  if (!current_.Offset())
    applied_start_width_ = false;

  LineLayoutText layout_text(current_.GetLineLayoutItem());

  // If we have left a no-wrap inline and entered an autowrap inline while
  // ignoring spaces then we need to mark the start of the autowrap inline as a
  // potential linebreak now.
  if (auto_wrap_ && !ComputedStyle::AutoWrap(last_ws_) && ignoring_spaces_) {
    width_.Commit();
    line_break_.MoveToStartOf(current_.GetLineLayoutItem());
  }

  const ComputedStyle& style = layout_text.StyleRef(line_info_.IsFirstLine());
  const Font& font = style.GetFont();

  unsigned last_space = current_.Offset();
  unsigned next_grapheme_cluster = 0;
  float word_spacing = current_style_->WordSpacing();
  float last_space_word_spacing = 0;
  float word_spacing_for_word_measurement = 0;

  float width_from_last_breaking_opportunity = width_.UncommittedWidth();
  float char_width = 0;
  // Auto-wrapping text should wrap in the middle of a word only if it could not
  // wrap before the word, which is only possible if the word is the first thing
  // on the line, that is, if |w| is zero.
  bool break_words = current_style_->BreakWords() &&
                     ((auto_wrap_ && !width_.CommittedWidth()) ||
                      curr_ws_ == EWhiteSpace::kPre);
  bool mid_word_break = false;
  bool break_all =
      current_style_->WordBreak() == EWordBreak::kBreakAll && auto_wrap_;
  bool keep_all =
      current_style_->WordBreak() == EWordBreak::kKeepAll && auto_wrap_;
  bool prohibit_break_inside = current_style_->HasTextCombine() &&
                               layout_text.IsCombineText() &&
                               LineLayoutTextCombine(layout_text).IsCombined();

  // This is currently only used for word-break: break-all, specifically for the
  // case where we have a break opportunity within a word, then a string of non-
  // breakable content that ends up making our word wider than the current line.
  // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html
  float width_measurement_at_last_break_opportunity = 0;

  Hyphenation* hyphenation = auto_wrap_ ? style.GetHyphenation() : nullptr;
  bool disable_soft_hyphen = style.GetHyphens() == Hyphens::kNone;
  float hyphen_width = 0;
  bool is_line_empty = line_info_.IsEmpty();

  if (layout_text.IsSVGInlineText()) {
    break_words = false;
    break_all = false;
    keep_all = false;
  }

  // Use LineBreakType::Normal for break-all. When a word does not fit,
  // rewindToMidWordBreak() finds the mid-word break point.
  LineBreakType line_break_type =
      keep_all ? LineBreakType::kKeepAll : LineBreakType::kNormal;
  bool can_break_mid_word = break_all || break_words;
  int next_breakable_position_for_break_all = -1;

  if (layout_text.IsWordBreak()) {
    width_.Commit();
    line_break_.MoveToStartOf(current_.GetLineLayoutItem());
    DCHECK_EQ(current_.Offset(), layout_text.TextLength());
  }

  if (layout_text_info_.text_ != layout_text) {
    layout_text_info_.text_ = layout_text;
    layout_text_info_.font_ = &font;
    layout_text_info_.line_break_iterator_.ResetStringAndReleaseIterator(
        layout_text.GetText(), style.LocaleForLineBreakIterator());
  } else if (layout_text_info_.font_ != &font) {
    layout_text_info_.font_ = &font;
  }

  // Non-zero only when kerning is enabled, in which case we measure
  // words with their trailing space, then subtract its width.
  float word_trailing_space_width =
      (font.GetFontDescription().GetTypesettingFeatures() & kKerning)
          ? font.Width(ConstructTextRun(font, &kSpaceCharacter, 1, style,
                                        style.Direction())) +
                word_spacing
          : 0;

  UChar last_character = layout_text_info_.line_break_iterator_.LastCharacter();
  UChar second_to_last_character =
      layout_text_info_.line_break_iterator_.SecondToLastCharacter();
  for (; current_.Offset() < layout_text.TextLength();
       current_.FastIncrementInTextNode()) {
    bool previous_character_is_space = current_character_is_space_;
    UChar c = current_.Current();
    SetCurrentCharacterIsSpace(c);

    // Auto-wrapping text should not wrap in the middle of a word if it has
    // an opportunity to break at a leading white-space.
    // TODO (jfernandez): This change is questionable, but it's required to
    // achieve the expected behavior for 'break-word' (cases 2.1 and 2.2), while
    // keeping current behavior for 'break-all' (cases 4.1 and 4.2)
    // https://github.com/w3c/csswg-drafts/issues/2907
    if (single_leading_space_)
      can_break_mid_word = break_all;

    if (!collapse_white_space_ || !current_character_is_space_) {
      line_info_.SetEmpty(false);
      width_.SetTrailingWhitespaceWidth(0);
    }

    if (c == kSoftHyphenCharacter && auto_wrap_ && !hyphen_width &&
        !disable_soft_hyphen) {
      hyphen_width = layout_text.HyphenWidth(
          font, TextDirectionFromUnicode(resolver_.GetPosition().Direction()));
      width_.AddUncommittedWidth(hyphen_width);
    }

    bool apply_word_spacing = false;

    // Determine if we should try breaking in the middle of a word.
    if (can_break_mid_word && !mid_word_break &&
        current_.Offset() >= next_grapheme_cluster) {
      mid_word_break =
          ShouldMidWordBreak(c, layout_text, font, next_grapheme_cluster,
                             char_width, width_from_last_breaking_opportunity,
                             break_all, next_breakable_position_for_break_all);
    }

    // Determine if we are in the whitespace between words.
    int next_breakable_position = current_.NextBreakablePosition();
    bool between_words =
        c == kNewlineCharacter ||
        (curr_ws_ != EWhiteSpace::kPre && !at_start_ &&
         layout_text_info_.line_break_iterator_.IsBreakable(
             current_.Offset(), next_breakable_position, line_break_type) &&
         (!disable_soft_hyphen ||
          current_.PreviousInSameNode() != kSoftHyphenCharacter));
    current_.SetNextBreakablePosition(next_breakable_position);

    // If we're in the middle of a word or at the start of a new one and can't
    // break there, then continue to the next character.
    if (!between_words && !mid_word_break) {
      if (ignoring_spaces_) {
        // Stop ignoring spaces and begin at this
        // new point.
        last_space_word_spacing = apply_word_spacing ? word_spacing : 0;
        word_spacing_for_word_measurement =
            (apply_word_spacing && word_measurements.back().width)
                ? word_spacing
                : 0;
        StopIgnoringSpaces(last_space);
      }

      PrepareForNextCharacter(layout_text, prohibit_break_inside,
                              previous_character_is_space);
      at_start_ = false;
      NextCharacter(c, last_character, second_to_last_character);
      continue;
    }

    // If we're collapsing space and we're at a collapsible space such as a
    // space or tab, continue to the next character.
    if (ignoring_spaces_ && current_character_is_space_) {
      last_space_word_spacing = 0;
      // Just keep ignoring these spaces.
      NextCharacter(c, last_character, second_to_last_character);
      continue;
    }

    // We're in the first whitespace after a word or in whitespace that we don't
    // collapse, which means we may have a breaking opportunity here.

    // If we're here and we're collapsing space then the current character isn't
    // a form of whitespace we can collapse. Stop ignoring spaces.
    bool stopped_ignoring_spaces = false;
    if (ignoring_spaces_) {
      last_space_word_spacing = 0;
      word_spacing_for_word_measurement = 0;
      stopped_ignoring_spaces = true;
      StopIgnoringSpaces(last_space);
    }

    // Update our tally of the width since the last breakable position with the
    // width of the word we're now at the end of.
    float last_width_measurement;
    WordMeasurement& word_measurement = CalculateWordWidth(
        word_measurements, layout_text, last_space, last_width_measurement,
        word_spacing_for_word_measurement, font, word_trailing_space_width, c);
    last_width_measurement += last_space_word_spacing;
    width_.AddUncommittedWidth(last_width_measurement);

    // We keep track of the total width contributed by trailing space as we
    // often want to exclude it when determining
    // if a run fits on a line.
    if (collapse_white_space_ && previous_character_is_space &&
        current_character_is_space_ && last_width_measurement)
      width_.SetTrailingWhitespaceWidth(last_width_measurement);

    // If this is the end of the first word in run of text then make sure we
    // apply the width from any leading inlines.
    // For example: '<span style="margin-left: 5px;"><span style="margin-left:
    // 10px;">FirstWord</span></span>' would apply a width of 15px from the two
    // span ancestors.
    if (!applied_start_width_) {
      width_.AddUncommittedWidth(InlineLogicalWidthFromAncestorsIfNeeded(
                                     current_.GetLineLayoutItem(), true, false)
                                     .ToFloat());
      applied_start_width_ = true;
    }

    mid_word_break = false;
    if (!width_.FitsOnLine()) {
      if (hyphenation && (next_object_ || is_line_empty ||
                          HasVisibleText(layout_text, current_.Offset()))) {
        width_.AddUncommittedWidth(-word_measurement.width);
        DCHECK_EQ(last_space,
                  static_cast<unsigned>(word_measurement.start_offset));
        DCHECK_EQ(current_.Offset(),
                  static_cast<unsigned>(word_measurement.end_offset));
        if (Hyphenate(layout_text, style, font, *hyphenation,
                      last_space_word_spacing, word_measurement)) {
          width_.AddUncommittedWidth(word_measurement.width);
          hyphenated = true;
          at_end_ = true;
          return false;
        }
        width_.AddUncommittedWidth(word_measurement.width);
      }
      if (can_break_mid_word) {
        width_.AddUncommittedWidth(-word_measurement.width);
        if (RewindToMidWordBreak(layout_text, style, font, break_all,
                                 word_measurement)) {
          last_width_measurement =
              word_measurement.width + last_space_word_spacing;
          mid_word_break = true;
        }
        width_.AddUncommittedWidth(word_measurement.width);
      }
    }

    // If we haven't hit a breakable position yet and already don't fit on the
    // line try to move below any floats.
    if (!width_.CommittedWidth() && auto_wrap_ && !width_.FitsOnLine() &&
        !width_measurement_at_last_break_opportunity) {
      float available_width_before = width_.AvailableWidth();
      width_.FitBelowFloats(line_info_.IsFirstLine());
      // If availableWidth changes by moving the line below floats, needs to
      // measure midWordBreak again.
      if (mid_word_break && available_width_before != width_.AvailableWidth())
        mid_word_break = false;
    }

    // If there is a soft-break available at this whitespace position then take
    // it.
    apply_word_spacing = word_spacing && current_character_is_space_;
    if (CanBreakAtWhitespace(
            break_words, word_measurement, stopped_ignoring_spaces, char_width,
            hyphenated, disable_soft_hyphen, hyphen_width, between_words,
            mid_word_break, can_break_mid_word, previous_character_is_space,
            last_width_measurement, layout_text, font, apply_word_spacing,
            word_spacing))
      return false;

    // If there is a hard-break available at this whitespace position then take
    // it.
    if (c == kNewlineCharacter && preserves_newline_) {
      if (!stopped_ignoring_spaces && current_.Offset())
        line_midpoint_state_.EnsureCharacterGetsLineBox(current_);
      line_break_.MoveTo(current_.GetLineLayoutItem(), current_.Offset(),
                         current_.NextBreakablePosition());
      line_break_.Increment();
      line_info_.SetPreviousLineBrokeCleanly(true);
      return true;
    }

    // Auto-wrapping text should not wrap in the middle of a word once it has
    // had an opportunity to break after a word.
    if (auto_wrap_ && between_words) {
      width_.Commit();
      width_from_last_breaking_opportunity = 0;
      line_break_.MoveTo(current_.GetLineLayoutItem(), current_.Offset(),
                         current_.NextBreakablePosition());
      break_words = false;
      can_break_mid_word = break_all;
      width_measurement_at_last_break_opportunity = last_width_measurement;
    }

    if (between_words) {
      last_space_word_spacing = apply_word_spacing ? word_spacing : 0;
      word_spacing_for_word_measurement =
          (apply_word_spacing && word_measurement.width) ? word_spacing : 0;
      last_space = current_.Offset();
    }

    // If we encounter a newline, or if we encounter a second space, we need to
    // go ahead and break up this run and enter a mode where we start collapsing
    // spaces.
    if (!ignoring_spaces_ && current_style_->CollapseWhiteSpace()) {
      if (current_character_is_space_ && previous_character_is_space) {
        ignoring_spaces_ = true;

        // We just entered a mode where we are ignoring spaces. Create a
        // midpoint to terminate the run before the second space.
        line_midpoint_state_.StartIgnoringSpaces(start_of_ignored_spaces_);
        trailing_objects_.UpdateMidpointsForTrailingObjects(
            line_midpoint_state_, InlineIterator(),
            TrailingObjects::kDoNotCollapseFirstSpace);
      }
    }

    PrepareForNextCharacter(layout_text, prohibit_break_inside,
                            previous_character_is_space);
    at_start_ = false;
    is_line_empty = line_info_.IsEmpty();
    NextCharacter(c, last_character, second_to_last_character);
  }

  layout_text_info_.line_break_iterator_.SetPriorContext(
      last_character, second_to_last_character);

  word_measurements.Grow(word_measurements.size() + 1);
  WordMeasurement& word_measurement = word_measurements.back();
  word_measurement.layout_text = layout_text;

  // IMPORTANT: current.offset() is > layoutText.textLength() here!
  float last_width_measurement = 0;
  word_measurement.start_offset = last_space;
  word_measurement.end_offset = current_.Offset();
  if (!ignoring_spaces_) {
    last_width_measurement = TextWidth(
        layout_text, last_space, current_.Offset() - last_space, font,
        width_.CurrentWidth(), collapse_white_space_,
        &word_measurement.fallback_fonts, &word_measurement.glyph_bounds);
    word_measurement.width =
        last_width_measurement + word_spacing_for_word_measurement;
    word_measurement.glyph_bounds.Move(word_spacing_for_word_measurement, 0);
  }
  last_width_measurement += last_space_word_spacing;

  LayoutUnit additional_width_from_ancestors =
      InlineLogicalWidthFromAncestorsIfNeeded(current_.GetLineLayoutItem(),
                                              !applied_start_width_,
                                              include_end_width_);
  width_.AddUncommittedWidth(last_width_measurement +
                             additional_width_from_ancestors);

  if (collapse_white_space_ && current_character_is_space_ &&
      last_width_measurement)
    width_.SetTrailingWhitespaceWidth(last_width_measurement +
                                      additional_width_from_ancestors);

  include_end_width_ = false;

  if (!ignoring_spaces_ && !width_.FitsOnLine()) {
    if (hyphenation && (next_object_ || is_line_empty)) {
      width_.AddUncommittedWidth(-word_measurement.width);
      DCHECK_EQ(last_space,
                static_cast<unsigned>(word_measurement.start_offset));
      DCHECK_EQ(current_.Offset(),
                static_cast<unsigned>(word_measurement.end_offset));
      if (Hyphenate(layout_text, style, font, *hyphenation,
                    last_space_word_spacing, word_measurement)) {
        hyphenated = true;
        at_end_ = true;
      }
      width_.AddUncommittedWidth(word_measurement.width);
    }
    if (!hyphenated && IsBreakAtSoftHyphen() && !disable_soft_hyphen) {
      hyphenated = true;
      at_end_ = true;
    }
    if (!hyphenated && can_break_mid_word) {
      width_.AddUncommittedWidth(-word_measurement.width);
      if (RewindToMidWordBreak(layout_text, style, font, break_all,
                               word_measurement)) {
        width_.AddUncommittedWidth(word_measurement.width);
        width_.Commit();
        at_end_ = true;
      } else {
        width_.AddUncommittedWidth(word_measurement.width);
        if (width_.CommittedWidth())
          at_end_ = true;
      }
    }
  }
  return false;
}

inline void BreakingContext::PrepareForNextCharacter(
    const LineLayoutText& layout_text,
    bool& prohibit_break_inside,
    bool previous_character_is_space) {
  if (layout_text.IsSVGInlineText() && current_.Offset()) {
    // Force creation of new InlineBoxes for each absolute positioned character
    // (those that start new text chunks).
    if (LineLayoutSVGInlineText(layout_text)
            .CharacterStartsNewTextChunk(current_.Offset()))
      line_midpoint_state_.EnsureCharacterGetsLineBox(current_);
  }
  if (prohibit_break_inside) {
    current_.SetNextBreakablePosition(layout_text.TextLength());
    prohibit_break_inside = false;
  }
  if (current_character_is_space_ && !previous_character_is_space) {
    start_of_ignored_spaces_.SetLineLayoutItem(current_.GetLineLayoutItem());
    start_of_ignored_spaces_.SetOffset(current_.Offset());
  }
  if (!current_character_is_space_ && previous_character_is_space) {
    if (auto_wrap_ && current_style_->BreakOnlyAfterWhiteSpace()) {
      line_break_.MoveTo(current_.GetLineLayoutItem(), current_.Offset(),
                         current_.NextBreakablePosition());
      if (current_.Offset() == current_start_offset_ + 1)
        single_leading_space_ = true;
    }
  }
  if (collapse_white_space_ && current_character_is_space_ && !ignoring_spaces_)
    trailing_objects_.SetTrailingWhitespace(
        LineLayoutText(current_.GetLineLayoutItem()));
  else if (!current_style_->CollapseWhiteSpace() ||
           !current_character_is_space_)
    trailing_objects_.Clear();
}

inline void BreakingContext::StopIgnoringSpaces(unsigned& last_space) {
  ignoring_spaces_ = false;
  // e.g., "Foo    goo", don't add in any of the ignored spaces.
  last_space = current_.Offset();
  line_midpoint_state_.StopIgnoringSpaces(
      InlineIterator(nullptr, current_.GetLineLayoutItem(), current_.Offset()));
}

inline WordMeasurement& BreakingContext::CalculateWordWidth(
    WordMeasurements& word_measurements,
    LineLayoutText& layout_text,
    unsigned last_space,
    float& last_width_measurement,
    float word_spacing_for_word_measurement,
    const Font& font,
    float word_trailing_space_width,
    UChar c) {
  word_measurements.Grow(word_measurements.size() + 1);
  WordMeasurement& word_measurement = word_measurements.back();
  word_measurement.layout_text = layout_text;
  word_measurement.end_offset = current_.Offset();
  word_measurement.start_offset = last_space;

  if (word_trailing_space_width && c == kSpaceCharacter)
    last_width_measurement =
        TextWidth(layout_text, last_space, current_.Offset() + 1 - last_space,
                  font, width_.CurrentWidth(), collapse_white_space_,
                  &word_measurement.fallback_fonts,
                  &word_measurement.glyph_bounds) -
        word_trailing_space_width;
  else
    last_width_measurement = TextWidth(
        layout_text, last_space, current_.Offset() - last_space, font,
        width_.CurrentWidth(), collapse_white_space_,
        &word_measurement.fallback_fonts, &word_measurement.glyph_bounds);

  word_measurement.width =
      last_width_measurement + word_spacing_for_word_measurement;
  word_measurement.glyph_bounds.Move(word_spacing_for_word_measurement, 0);
  return word_measurement;
}

inline bool BreakingContext::TrailingSpaceExceedsAvailableWidth(
    bool can_break_mid_word,
    const LineLayoutText& layout_text,
    WordMeasurement& word_measurement,
    bool apply_word_spacing,
    bool word_spacing,
    const Font& font) {
  // If we break only after white-space, consider the current character
  // as candidate width for this line.
  if (width_.FitsOnLine() && current_character_is_space_ &&
      current_style_->BreakOnlyAfterWhiteSpace()) {
    float char_width = TextWidth(layout_text, current_.Offset(), 1, font,
                                 width_.CurrentWidth(), collapse_white_space_,
                                 &word_measurement.fallback_fonts,
                                 &word_measurement.glyph_bounds) +
                       (apply_word_spacing ? word_spacing : 0);
    // Check if line is too big even without the extra space
    // at the end of the line. If it is not, do nothing.
    // If the line needs the extra whitespace to be too long,
    // then move the line break to the space and skip all
    // additional whitespace.
    if (!width_.FitsOnLine(char_width)) {
      line_break_.MoveTo(current_.GetLineLayoutItem(), current_.Offset(),
                         current_.NextBreakablePosition());
      SkipTrailingWhitespace(line_break_, line_info_);
      return true;
    }
  }
  return false;
}

inline bool BreakingContext::CanBreakAtWhitespace(
    bool break_words,
    WordMeasurement& word_measurement,
    bool stopped_ignoring_spaces,
    float char_width,
    bool& hyphenated,
    bool disable_soft_hyphen,
    float& hyphen_width,
    bool between_words,
    bool mid_word_break,
    bool can_break_mid_word,
    bool previous_character_is_space,
    float last_width_measurement,
    const LineLayoutText& layout_text,
    const Font& font,
    bool apply_word_spacing,
    float word_spacing) {
  if (!auto_wrap_ && !break_words)
    return false;

  // If we break only after white-space, consider the current character
  // as candidate width for this line.
  if (mid_word_break ||
      TrailingSpaceExceedsAvailableWidth(can_break_mid_word, layout_text,
                                         word_measurement, apply_word_spacing,
                                         word_spacing, font) ||
      !width_.FitsOnLine()) {
    if (line_break_.AtTextParagraphSeparator()) {
      if (!stopped_ignoring_spaces && current_.Offset() > 0)
        line_midpoint_state_.EnsureCharacterGetsLineBox(current_);
      line_break_.Increment();
      line_info_.SetPreviousLineBrokeCleanly(true);
      word_measurement.end_offset = line_break_.Offset();
    }
    if (IsBreakAtSoftHyphen() && !disable_soft_hyphen)
      hyphenated = true;
    if (line_break_.Offset() &&
        line_break_.Offset() != (unsigned)word_measurement.end_offset &&
        !word_measurement.width) {
      if (char_width) {
        word_measurement.end_offset = line_break_.Offset();
        word_measurement.width = char_width;
      }
    }
    // Didn't fit. Jump to the end unless there's still an opportunity to
    // collapse whitespace.
    if (ignoring_spaces_ || !collapse_white_space_ ||
        !current_character_is_space_ || !previous_character_is_space) {
      at_end_ = true;
      return true;
    }
  } else {
    if (!between_words || (mid_word_break && !auto_wrap_))
      width_.AddUncommittedWidth(-last_width_measurement);
    if (hyphen_width) {
      // Subtract the width of the soft hyphen out since we fit on a line.
      width_.AddUncommittedWidth(-hyphen_width);
      hyphen_width = 0;
    }
  }
  return false;
}

inline void BreakingContext::CommitAndUpdateLineBreakIfNeeded() {
  bool check_for_break = auto_wrap_;
  if (width_.CommittedWidth() && !width_.FitsOnLine() &&
      line_break_.GetLineLayoutItem() && curr_ws_ == EWhiteSpace::kNowrap) {
    // If this nowrap item fits but its trailing spaces does not, and if the
    // next item is auto-wrap, break before the next item.
    // TODO(kojii): This case should be handled when we read next item.
    if (width_.FitsOnLine(0, kExcludeWhitespace) &&
        (!next_object_ || next_object_.StyleRef().AutoWrap())) {
      width_.Commit();
      line_break_.MoveToStartOf(next_object_);
    }
    check_for_break = true;
  } else if (next_object_ && current_.GetLineLayoutItem().IsText() &&
             next_object_.IsText() && !next_object_.IsBR() &&
             (auto_wrap_ || next_object_.StyleRef().AutoWrap())) {
    if (auto_wrap_ && current_character_is_space_) {
      check_for_break = true;
    } else {
      LineLayoutText next_text(next_object_);
      if (next_text.TextLength()) {
        UChar c = next_text.CharacterAt(0);
        // If the next item on the line is text, and if we did not end with
        // a space, then the next text run continues our word (and so it needs
        // to keep adding to the uncommitted width. Just update and continue.
        check_for_break =
            !current_character_is_space_ &&
            (c == kSpaceCharacter || c == kTabulationCharacter ||
             (c == kNewlineCharacter && !next_object_.PreservesNewline()));
      } else if (next_text.IsWordBreak()) {
        check_for_break = true;
      }

      if (!width_.FitsOnLine() && !width_.CommittedWidth())
        width_.FitBelowFloats(line_info_.IsFirstLine());

      bool can_place_on_line =
          width_.FitsOnLine() || !auto_wrap_was_ever_true_on_line_;
      if (can_place_on_line && check_for_break) {
        width_.Commit();
        line_break_.MoveToStartOf(next_object_);
      }
    }
  }

  if (check_for_break && !width_.FitsOnLine()) {
    // if we have floats, try to get below them.
    if (current_character_is_space_ && !ignoring_spaces_ &&
        current_style_->CollapseWhiteSpace())
      trailing_objects_.Clear();

    // If we are going to break before a float on an object that is just
    // collapsible white space then make sure the line break is moved to
    // the float.
    if (width_.FitsOnLine(0, kExcludeWhitespace) && next_object_ &&
        next_object_.IsFloating() && current_.GetLineLayoutItem().IsText() &&
        LineLayoutText(current_.GetLineLayoutItem())
            .IsAllCollapsibleWhitespace()) {
      width_.Commit();
      line_break_.MoveToStartOf(next_object_);
    }

    if (width_.CommittedWidth()) {
      at_end_ = true;
      return;
    }

    width_.FitBelowFloats(line_info_.IsFirstLine());

    // |width| may have been adjusted because we got shoved down past a float
    // (thus giving us more room), so we need to retest, and only jump to the
    // the end label if we still don't fit on the line. -dwh
    if (!width_.FitsOnLine()) {
      at_end_ = true;
      return;
    }
  } else if (block_style_->AutoWrap() && !width_.FitsOnLine() &&
             !width_.CommittedWidth()) {
    // If the container autowraps but the current child does not then we still
    // need to ensure that it wraps and moves below any floats.
    width_.FitBelowFloats(line_info_.IsFirstLine());
  }

  if (!current_.GetLineLayoutItem().IsFloatingOrOutOfFlowPositioned()) {
    last_object_ = current_.GetLineLayoutItem();
    if (last_object_.IsAtomicInlineLevel() && auto_wrap_ &&
        (!last_object_.IsListMarker() ||
         LineLayoutListMarker(last_object_).IsInside()) &&
        !last_object_.IsRubyRun()) {
      width_.Commit();
      line_break_.MoveToStartOf(next_object_);
    }
  }
}

inline IndentTextOrNot RequiresIndent(bool is_first_line,
                                      bool is_after_hard_line_break,
                                      const ComputedStyle& style) {
  IndentTextOrNot indent_text = kDoNotIndentText;
  if (is_first_line ||
      (is_after_hard_line_break &&
       style.GetTextIndentLine() != TextIndentLine::kFirstLine))
    indent_text = kIndentText;

  if (style.GetTextIndentType() == TextIndentType::kHanging)
    indent_text = indent_text == kIndentText ? kDoNotIndentText : kIndentText;

  return indent_text;
}

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_BREAKING_CONTEXT_INLINE_HEADERS_H_
