// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/layout/text_box.h"

#include <algorithm>
#include <limits>

#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/shadow_value.h"
#include "cobalt/layout/render_tree_animations.h"
#include "cobalt/layout/used_style.h"
#include "cobalt/layout/white_space_processing.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/filter_node.h"
#include "cobalt/render_tree/glyph_buffer.h"
#include "cobalt/render_tree/text_node.h"

namespace cobalt {
namespace layout {

TextBox::TextBox(const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
                     css_computed_style_declaration,
                 const scoped_refptr<Paragraph>& paragraph,
                 int32 text_start_position, int32 text_end_position,
                 bool has_trailing_line_break, bool is_product_of_split,
                 UsedStyleProvider* used_style_provider,
                 LayoutStatTracker* layout_stat_tracker)
    : Box(css_computed_style_declaration, used_style_provider,
          layout_stat_tracker),
      paragraph_(paragraph),
      text_start_position_(text_start_position),
      text_end_position_(text_end_position),
      truncated_text_start_position_(text_start_position),
      truncated_text_end_position_(text_end_position),
      previous_truncated_text_start_position_(text_start_position),
      previous_truncated_text_end_position_(text_end_position),
      truncated_text_offset_from_left_(0),
      used_font_(used_style_provider->GetUsedFontList(
          css_computed_style_declaration->data()->font_family(),
          css_computed_style_declaration->data()->font_size(),
          css_computed_style_declaration->data()->font_style(),
          css_computed_style_declaration->data()->font_weight())),
      text_has_leading_white_space_(false),
      text_has_trailing_white_space_(false),
      should_collapse_leading_white_space_(false),
      should_collapse_trailing_white_space_(false),
      has_trailing_line_break_(has_trailing_line_break),
      is_product_of_split_(is_product_of_split),
      update_size_results_valid_(false),
      ascent_(0) {
  DCHECK(text_start_position_ <= text_end_position_);

  UpdateTextHasLeadingWhiteSpace();
  UpdateTextHasTrailingWhiteSpace();
}

Box::Level TextBox::GetLevel() const { return kInlineLevel; }

TextBox* TextBox::AsTextBox() { return this; }
const TextBox* TextBox::AsTextBox() const { return this; }

bool TextBox::ValidateUpdateSizeInputs(const LayoutParams& params) {
  // Also take into account mutable local state about (at least) whether white
  // space should be collapsed or not.
  if (Box::ValidateUpdateSizeInputs(params) && update_size_results_valid_) {
    return true;
  } else {
    update_size_results_valid_ = true;
    return false;
  }
}

LayoutUnit TextBox::GetInlineLevelBoxHeight() const { return line_height_; }

LayoutUnit TextBox::GetInlineLevelTopMargin() const {
  return inline_top_margin_;
}

void TextBox::UpdateContentSizeAndMargins(const LayoutParams& layout_params) {
  // Anonymous boxes do not have margins.
  DCHECK(GetUsedMarginLeftIfNotAuto(computed_style(),
                                    layout_params.containing_block_size)
             ->EqualOrNaN(LayoutUnit()));
  DCHECK(GetUsedMarginTopIfNotAuto(computed_style(),
                                   layout_params.containing_block_size)
             ->EqualOrNaN(LayoutUnit()));
  DCHECK(GetUsedMarginRightIfNotAuto(computed_style(),
                                     layout_params.containing_block_size)
             ->EqualOrNaN(LayoutUnit()));
  DCHECK(GetUsedMarginBottomIfNotAuto(computed_style(),
                                      layout_params.containing_block_size)
             ->EqualOrNaN(LayoutUnit()));

  // The non-collapsible content size only needs to be calculated if
  // |non_collapsible_text_width_| is unset. This indicates that either the
  // width has not previously been calculated for this box, or that the width
  // was invalidated as the result of a split.
  if (!non_collapsible_text_width_) {
    const scoped_refptr<cssom::PropertyValue>& line_height =
        computed_style()->line_height();

    // Factor in all of the fonts needed by the text when generating font
    // metrics if the line height is set to normal:
    // "When an element contains text that is rendered in more than one font,
    // user agents may determine the 'normal' 'line-height' value according to
    // the largest font size."
    //   https://www.w3.org/TR/CSS21/visudet.html#line-height
    bool use_text_fonts_to_generate_font_metrics =
        (line_height == cssom::KeywordValue::GetNormal());

    render_tree::FontVector text_fonts;
    int32 text_start_position = GetNonCollapsibleTextStartPosition();
    non_collapsible_text_width_ =
        HasNonCollapsibleText()
            ? LayoutUnit(used_font_->GetTextWidth(
                  paragraph_->GetTextBuffer() + text_start_position,
                  GetNonCollapsibleTextLength(),
                  paragraph_->IsRTL(text_start_position),
                  use_text_fonts_to_generate_font_metrics ? &text_fonts : NULL))
            : LayoutUnit();

    // The line height values are only calculated when one of two conditions are
    // met:
    //  1. |baseline_offset_from_top_| has not previously been set, meaning that
    //     the line height has never been calculated for this box.
    //  2. |use_text_fonts_to_generate_font_metrics| is true, meaning that the
    //     line height values depend on the content of the text itself. When
    //     this is the case, the line height value is not constant and a split
    //     in the text box can result in the line height values changing.
    if (!baseline_offset_from_top_ || use_text_fonts_to_generate_font_metrics) {
      set_margin_left(LayoutUnit());
      set_margin_top(LayoutUnit());
      set_margin_right(LayoutUnit());
      set_margin_bottom(LayoutUnit());

      render_tree::FontMetrics font_metrics =
          used_font_->GetFontMetrics(text_fonts);

      UsedLineHeightProvider used_line_height_provider(
          font_metrics, computed_style()->font_size());
      line_height->Accept(&used_line_height_provider);
      set_height(LayoutUnit(font_metrics.em_box_height()));
      baseline_offset_from_top_ =
          used_line_height_provider.baseline_offset_from_top();
      line_height_ = used_line_height_provider.used_line_height();
      inline_top_margin_ = used_line_height_provider.half_leading();
      ascent_ = font_metrics.ascent();
    }
  }

  set_width(GetLeadingWhiteSpaceWidth() + *non_collapsible_text_width_ +
            GetTrailingWhiteSpaceWidth());
}

WrapResult TextBox::TryWrapAt(WrapAtPolicy wrap_at_policy,
                              WrapOpportunityPolicy wrap_opportunity_policy,
                              bool is_line_existence_justified,
                              LayoutUnit available_width,
                              bool should_collapse_trailing_white_space) {
  DCHECK(!IsAbsolutelyPositioned());

  bool style_allows_break_word =
      computed_style()->overflow_wrap() == cssom::KeywordValue::GetBreakWord();

  if (!ShouldProcessWrapOpportunityPolicy(wrap_opportunity_policy,
                                          style_allows_break_word)) {
    return kWrapResultNoWrap;
  }

  // Even when the text box's style prevents wrapping, wrapping can still occur
  // before the box if the following requirements are met:
  // - The text box is not the product of a split. If it is, and this box's
  //   style prevents text wrapping, then the previous box also prevents text
  //   wrapping, and no wrap should occur between them.
  // - The line's existence has already been justified. Wrapping cannot occur
  //   prior to that.
  // - Whitespace precedes the text box. This can only occur in the case where
  //   the preceding box allows wrapping, otherwise a no-breaking space will
  //   have been appended (the one exception to this is when this box was the
  //   product of a split, but that case is already handled above).
  if (!DoesAllowTextWrapping(computed_style()->white_space())) {
    if (!is_product_of_split_ && is_line_existence_justified &&
        text_start_position_ > 0 &&
        paragraph_->IsCollapsibleWhiteSpace(text_start_position_ - 1)) {
      return kWrapResultWrapBefore;
    } else {
      return kWrapResultNoWrap;
    }
  }

  // If the line existence is already justified, then leading whitespace can be
  // included in the wrap search, as it provides a wrappable point. If it isn't,
  // then the leading whitespace is skipped, because the line cannot wrap before
  // it is justified.
  int32 start_position = is_line_existence_justified
                             ? text_start_position_
                             : GetNonCollapsibleTextStartPosition();

  int32 wrap_position = GetWrapPosition(
      wrap_at_policy, wrap_opportunity_policy, is_line_existence_justified,
      available_width, should_collapse_trailing_white_space,
      style_allows_break_word, start_position);

  WrapResult wrap_result;
  // Wrapping at the text start position is only allowed when the line's
  // existence is already justified.
  if (wrap_position == text_start_position_ && is_line_existence_justified) {
    wrap_result = kWrapResultWrapBefore;
  } else if (wrap_position > start_position &&
             wrap_position < text_end_position_) {
    SplitAtPosition(wrap_position);
    wrap_result = kWrapResultSplitWrap;
  } else {
    wrap_result = kWrapResultNoWrap;
  }
  return wrap_result;
}

Box* TextBox::GetSplitSibling() const { return split_sibling_; }

bool TextBox::DoesFulfillEllipsisPlacementRequirement() const {
  // This box has non-collapsed text and fulfills the requirement that the first
  // character or inline-level element must appear on the line before ellipsing
  // can occur if it has non-collapsed characters.
  //   https://www.w3.org/TR/css3-ui/#propdef-text-overflow
  return GetNonCollapsedTextStartPosition() < GetNonCollapsedTextEndPosition();
}

void TextBox::DoPreEllipsisPlacementProcessing() {
  previous_truncated_text_start_position_ = truncated_text_start_position_;
  previous_truncated_text_end_position_ = truncated_text_end_position_;
  truncated_text_start_position_ = text_start_position_;
  truncated_text_end_position_ = text_end_position_;
}

void TextBox::DoPostEllipsisPlacementProcessing() {
  if (previous_truncated_text_start_position_ !=
          truncated_text_start_position_ ||
      previous_truncated_text_end_position_ != truncated_text_end_position_) {
    InvalidateRenderTreeNodesOfBoxAndAncestors();
  }
}

void TextBox::SplitBidiLevelRuns() {}

bool TextBox::TrySplitAtSecondBidiLevelRun() {
  int32 split_position;
  if (paragraph_->GetNextRunPosition(text_start_position_, &split_position) &&
      split_position < text_end_position_) {
    SplitAtPosition(split_position);
    return true;
  } else {
    return false;
  }
}

base::Optional<int> TextBox::GetBidiLevel() const {
  return paragraph_->GetBidiLevel(text_start_position_);
}

void TextBox::SetShouldCollapseLeadingWhiteSpace(
    bool should_collapse_leading_white_space) {
  if (should_collapse_leading_white_space_ !=
      should_collapse_leading_white_space) {
    should_collapse_leading_white_space_ = should_collapse_leading_white_space;
    update_size_results_valid_ = false;
  }
}

void TextBox::SetShouldCollapseTrailingWhiteSpace(
    bool should_collapse_trailing_white_space) {
  if (should_collapse_trailing_white_space_ !=
      should_collapse_trailing_white_space) {
    should_collapse_trailing_white_space_ =
        should_collapse_trailing_white_space;
    update_size_results_valid_ = false;
  }
}

bool TextBox::IsCollapsed() const {
  return !HasLeadingWhiteSpace() && !HasTrailingWhiteSpace() &&
         !HasNonCollapsibleText();
}

bool TextBox::HasLeadingWhiteSpace() const {
  return text_has_leading_white_space_ &&
         !should_collapse_leading_white_space_ &&
         (HasNonCollapsibleText() || !should_collapse_trailing_white_space_);
}

bool TextBox::HasTrailingWhiteSpace() const {
  return text_has_trailing_white_space_ &&
         !should_collapse_trailing_white_space_ &&
         (HasNonCollapsibleText() || !should_collapse_leading_white_space_);
}

bool TextBox::JustifiesLineExistence() const {
  return HasNonCollapsibleText() || has_trailing_line_break_;
}

bool TextBox::HasTrailingLineBreak() const { return has_trailing_line_break_; }

bool TextBox::AffectsBaselineInBlockFormattingContext() const {
  NOTREACHED() << "Should only be called in a block formatting context.";
  return true;
}

LayoutUnit TextBox::GetBaselineOffsetFromTopMarginEdge() const {
  return baseline_offset_from_top_.value_or(LayoutUnit());
}

namespace {
void PopulateBaseStyleForTextNode(
    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
    const scoped_refptr<cssom::MutableCSSComputedStyleData>&
        destination_style) {
  // NOTE: Properties set by PopulateBaseStyleForTextNode() should match the
  // properties used by SetupTextNodeFromStyle().
  destination_style->set_color(source_style->color());
}

void SetupTextNodeFromStyle(
    const scoped_refptr<const cssom::CSSComputedStyleData>& style,
    render_tree::TextNode::Builder* text_node_builder) {
  text_node_builder->color = GetUsedColor(style->color());
}

void AddTextShadows(render_tree::TextNode::Builder* builder,
                    cssom::PropertyListValue* shadow_list) {
  if (shadow_list->value().empty()) {
    return;
  }

  builder->shadows.emplace();
  builder->shadows->reserve(shadow_list->value().size());

  for (size_t s = 0; s < shadow_list->value().size(); ++s) {
    cssom::ShadowValue* shadow_value =
        base::polymorphic_downcast<cssom::ShadowValue*>(
            shadow_list->value()[s].get());

    math::Vector2dF offset(shadow_value->offset_x()->value(),
                           shadow_value->offset_y()->value());

    // Since most of a Gaussian fits within 3 standard deviations from
    // the mean, we setup here the Gaussian blur sigma to be a third of
    // the blur radius.
    float shadow_blur_sigma =
        shadow_value->blur_radius()
            ? GetUsedLength(shadow_value->blur_radius()).toFloat() / 3.0f
            : 0.0f;

    render_tree::ColorRGBA shadow_color = GetUsedColor(shadow_value->color());

    builder->shadows->push_back(
        render_tree::Shadow(offset, shadow_blur_sigma, shadow_color));
  }
}

}  // namespace

void TextBox::RenderAndAnimateContent(
    render_tree::CompositionNode::Builder* border_node_builder,
    ContainerBox* stacking_context) const {
  if (computed_style()->visibility() != cssom::KeywordValue::GetVisible()) {
    return;
  }

  DCHECK((border_left_width() + padding_left()).EqualOrNaN(LayoutUnit()));
  DCHECK((border_top_width() + padding_top()).EqualOrNaN(LayoutUnit()));

  // Only add the text node to the render tree if it actually has visible
  // content that isn't simply collapsible whitespace and a font isn't loading.
  // The font is treated as transparent if a font is currently being downloaded
  // and hasn't timed out: "In cases where textual content is loaded before
  // downloadable fonts are available, user agents may... render text
  // transparently with fallback fonts to avoid a flash of text using a fallback
  // font. In cases where the font download fails user agents must display text,
  // simply leaving transparent text is considered non-conformant behavior."
  //   https://www.w3.org/TR/css3-fonts/#font-face-loading
  if (HasNonCollapsibleText() && HasVisibleText() && used_font_->IsVisible()) {
    bool is_color_animated =
        animations()->IsPropertyAnimated(cssom::kColorProperty);

    render_tree::ColorRGBA used_color = GetUsedColor(computed_style()->color());

    const scoped_refptr<cssom::PropertyValue>& text_shadow =
        computed_style()->text_shadow();

    // Only render the text if it is not completely transparent, or if the
    // color is animated, in which case it could become non-transparent.
    if (used_color.a() > 0.0f || is_color_animated ||
        text_shadow != cssom::KeywordValue::GetNone()) {
      int32 text_start_position = GetVisibleTextStartPosition();
      int32 text_length = GetVisibleTextLength();

      scoped_refptr<render_tree::GlyphBuffer> glyph_buffer =
          used_font_->CreateGlyphBuffer(
              paragraph_->GetTextBuffer() + text_start_position, text_length,
              paragraph_->IsRTL(text_start_position));

      render_tree::TextNode::Builder text_node_builder(
          math::Vector2dF(truncated_text_offset_from_left_, ascent_),
          glyph_buffer, used_color);

      if (text_shadow != cssom::KeywordValue::GetNone()) {
        cssom::PropertyListValue* shadow_list =
            base::polymorphic_downcast<cssom::PropertyListValue*>(
                computed_style()->text_shadow().get());

        AddTextShadows(&text_node_builder, shadow_list);
      }

      scoped_refptr<render_tree::TextNode> text_node =
          new render_tree::TextNode(text_node_builder);

      // The render tree API considers text coordinates to be a position
      // of a baseline, offset the text node accordingly.
      scoped_refptr<render_tree::Node> node_to_add;
      if (is_color_animated) {
        render_tree::animations::AnimateNode::Builder animate_node_builder;
        AddAnimations<render_tree::TextNode>(
            base::Bind(&PopulateBaseStyleForTextNode),
            base::Bind(&SetupTextNodeFromStyle),
            *css_computed_style_declaration(), text_node,
            &animate_node_builder);
        node_to_add = new render_tree::animations::AnimateNode(
            animate_node_builder, text_node);
      } else {
        node_to_add = text_node;
      }
      border_node_builder->AddChild(node_to_add);
    }
  }
}

bool TextBox::IsTransformable() const { return false; }

#ifdef ENABLE_DEBUGGER

void TextBox::DumpClassName(std::ostream* stream) const {
  *stream << "TextBox ";
}

void TextBox::DumpProperties(std::ostream* stream) const {
  Box::DumpProperties(stream);

  *stream << "text_start=" << text_start_position_ << " "
          << "text_end=" << text_end_position_ << " ";

  *stream << std::boolalpha << "line_height=" << line_height_ << " "
          << "inline_top_margin=" << inline_top_margin_ << " "
          << "has_leading_white_space=" << HasLeadingWhiteSpace() << " "
          << "has_trailing_white_space=" << HasTrailingWhiteSpace() << " "
          << std::noboolalpha;

  *stream << "bidi_level=" << paragraph_->GetBidiLevel(text_start_position_)
          << " ";
}

void TextBox::DumpChildrenWithIndent(std::ostream* stream, int indent) const {
  Box::DumpChildrenWithIndent(stream, indent);

  DumpIndent(stream, indent);

  *stream << "\"" << GetNonCollapsibleText() << "\"\n";
}

#endif  // ENABLE_DEBUGGER

void TextBox::DoPlaceEllipsisOrProcessPlacedEllipsis(
    BaseDirection base_direction, LayoutUnit desired_offset,
    bool* is_placement_requirement_met, bool* is_placed,
    LayoutUnit* placed_offset) {
  // If the ellipsis has already been placed, then the text is fully truncated
  // by the ellipsis.
  if (*is_placed) {
    if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
                                                        text_start_position_)) {
      truncated_text_end_position_ = text_start_position_;
    } else {
      truncated_text_start_position_ = text_end_position_;
    }
    return;
  }

  // Otherwise, the ellipsis is being placed somewhere within this text box.
  *is_placed = true;

  LayoutUnit content_box_start_offset =
      GetContentBoxStartEdgeOffsetFromContainingBlock(base_direction);

  // Determine the available width in the content before to the desired offset.
  // This is the distance from the start edge of the content box to the desired
  // offset.
  LayoutUnit desired_content_offset =
      base_direction == kRightToLeftBaseDirection
          ? content_box_start_offset - desired_offset
          : desired_offset - content_box_start_offset;

  int32 start_position = GetNonCollapsedTextStartPosition();
  int32 end_position = GetNonCollapsedTextEndPosition();
  int32 found_position;
  LayoutUnit found_offset;

  // Attempt to find a break position allowing breaks anywhere within the text,
  // and not simply at soft wrap locations. If the placement requirement has
  // already been satisfied, then the ellipsis can appear anywhere within the
  // text box. Otherwise, it can only appear after the first character
  // (https://www.w3.org/TR/css3-ui/#propdef-text-overflow).
  if (paragraph_->FindBreakPosition(
          base_direction, false, used_font_, start_position, end_position,
          desired_content_offset, false, !(*is_placement_requirement_met),
          Paragraph::kBreakPolicyBreakWord, &found_position, &found_offset)) {
    // A usable break position was found. Calculate the placed offset using the
    // the break position's distance from the content box's start edge. In the
    // case where the base direction is right-to-left, the truncated text must
    // be offset to begin after the ellipsis.
    if (base_direction == kRightToLeftBaseDirection) {
      *placed_offset = content_box_start_offset - found_offset;
      truncated_text_offset_from_left_ =
          (*placed_offset - GetContentBoxLeftEdgeOffsetFromContainingBlock())
              .toFloat();
    } else {
      *placed_offset = content_box_start_offset + found_offset;
    }
    if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
                                                        start_position)) {
      truncated_text_end_position_ = found_position;
    } else {
      truncated_text_start_position_ = found_position;
    }
    // An acceptable break position was not found. If the placement requirement
    // was already met prior to this box, then the ellipsis doesn't require a
    // character from this box to appear prior to its position, so simply place
    // the ellipsis at the start edge of the box and fully truncate the text.
  } else if (is_placement_requirement_met) {
    *placed_offset =
        GetMarginBoxStartEdgeOffsetFromContainingBlock(base_direction);
    if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
                                                        start_position)) {
      truncated_text_end_position_ = text_start_position_;
    } else {
      truncated_text_start_position_ = text_end_position_;
    }
    // The placement requirement has not already been met. Given that an
    // acceptable break position was not found within the text, the ellipsis can
    // only be placed at the end edge of the box.
  } else {
    *placed_offset =
        GetMarginBoxEndEdgeOffsetFromContainingBlock(base_direction);
  }
}

void TextBox::UpdateTextHasLeadingWhiteSpace() {
  text_has_leading_white_space_ =
      text_start_position_ != text_end_position_ &&
      paragraph_->IsCollapsibleWhiteSpace(text_start_position_) &&
      DoesCollapseWhiteSpace(computed_style()->white_space());
}

void TextBox::UpdateTextHasTrailingWhiteSpace() {
  text_has_trailing_white_space_ =
      !has_trailing_line_break_ && text_start_position_ != text_end_position_ &&
      paragraph_->IsCollapsibleWhiteSpace(text_end_position_ - 1) &&
      DoesCollapseWhiteSpace(computed_style()->white_space());
}

int32 TextBox::GetWrapPosition(WrapAtPolicy wrap_at_policy,
                               WrapOpportunityPolicy wrap_opportunity_policy,
                               bool is_line_existence_justified,
                               LayoutUnit available_width,
                               bool should_collapse_trailing_white_space,
                               bool style_allows_break_word,
                               int32 start_position) {
  Paragraph::BreakPolicy break_policy =
      Paragraph::GetBreakPolicyFromWrapOpportunityPolicy(
          wrap_opportunity_policy, style_allows_break_word);

  int32 wrap_position = -1;
  switch (wrap_at_policy) {
    case kWrapAtPolicyBefore:
      // Wrapping before the box is only permitted when the line's existence is
      // justified.
      if (is_line_existence_justified &&
          paragraph_->IsBreakPosition(text_start_position_, break_policy)) {
        wrap_position = text_start_position_;
      } else {
        wrap_position = -1;
      }
      break;
    case kWrapAtPolicyLastOpportunityWithinWidth: {
      if (is_line_existence_justified) {
        // If the line existence is already justified, then the line can
        // potentially wrap after the box's leading whitespace. However, if that
        // whitespace has been collapsed, then we need to add its width to the
        // available width, because it'll be counted against the available width
        // while searching for the break position, but it won't impact the
        // length of the line.
        if (start_position != GetNonCollapsedTextStartPosition()) {
          available_width += LayoutUnit(used_font_->GetSpaceWidth());
        }
        // If the line's existence isn't already justified, then the line cannot
        // wrap on leading whitespace. Subtract the width of non-collapsed
        // whitespace from the available width, as the search is starting after
        // it.
      } else {
        available_width -= GetLeadingWhiteSpaceWidth();
      }

      // Attempt to find the last break position after the start position that
      // fits within the available width. Overflow is never allowed.
      LayoutUnit wrap_width;
      if (!paragraph_->FindBreakPosition(
              paragraph_->base_direction(), true, used_font_, start_position,
              text_end_position_, available_width,
              should_collapse_trailing_white_space, false, break_policy,
              &wrap_position, &wrap_width)) {
        // If no break position is found, but the line existence is already
        // justified, then check for text start position being a break position.
        // Wrapping before the box is permitted when the line's existence is
        // justified.
        if (is_line_existence_justified &&
            paragraph_->IsBreakPosition(text_start_position_, break_policy)) {
          wrap_position = text_start_position_;
        } else {
          wrap_position = -1;
        }
      }
      break;
    }
    case kWrapAtPolicyLastOpportunity:
      wrap_position = paragraph_->GetPreviousBreakPosition(text_end_position_,
                                                           break_policy);
      break;
    case kWrapAtPolicyFirstOpportunity: {
      // If the line is already justified, the wrap can occur at the start
      // position. Otherwise, the wrap cannot occur until after non-collapsible
      // text is included.
      int32 search_start_position =
          is_line_existence_justified ? start_position - 1 : start_position;
      wrap_position =
          paragraph_->GetNextBreakPosition(search_start_position, break_policy);
      break;
    }
  }
  return wrap_position;
}

void TextBox::SplitAtPosition(int32 split_start_position) {
  int32 split_end_position = text_end_position_;
  DCHECK_LT(split_start_position, split_end_position);

  text_end_position_ = split_start_position;
  truncated_text_end_position_ = text_end_position_;

  // The width is no longer valid for this box now that it has been split.
  update_size_results_valid_ = false;
  non_collapsible_text_width_ = base::nullopt;

  const bool kIsProductOfSplitTrue = true;

  scoped_refptr<TextBox> box_after_split(new TextBox(
      css_computed_style_declaration(), paragraph_, split_start_position,
      split_end_position, has_trailing_line_break_, kIsProductOfSplitTrue,
      used_style_provider(), layout_stat_tracker()));

  // Update the split sibling links.
  box_after_split->split_sibling_ = split_sibling_;
  split_sibling_ = box_after_split;

  // TODO: Set the text width of the box after split to
  //       |text_width_ - pre_split_width| to save a call to Skia/HarfBuzz.

  // Pass the trailing line break on to the sibling that retains the trailing
  // portion of the text and reset the value for this text box.
  has_trailing_line_break_ = false;

  // Update the paragraph end position white space now that this text box has
  // a new end position. The start position white space does not need to be
  // updated as it has not changed.
  UpdateTextHasTrailingWhiteSpace();
}

LayoutUnit TextBox::GetLeadingWhiteSpaceWidth() const {
  return HasLeadingWhiteSpace() ? LayoutUnit(used_font_->GetSpaceWidth())
                                : LayoutUnit();
}

LayoutUnit TextBox::GetTrailingWhiteSpaceWidth() const {
  return HasTrailingWhiteSpace() && HasNonCollapsibleText()
             ? LayoutUnit(used_font_->GetSpaceWidth())
             : LayoutUnit();
}

int32 TextBox::GetNonCollapsedTextStartPosition() const {
  return should_collapse_leading_white_space_
             ? GetNonCollapsibleTextStartPosition()
             : text_start_position_;
}

int32 TextBox::GetNonCollapsedTextEndPosition() const {
  return should_collapse_trailing_white_space_
             ? GetNonCollapsibleTextEndPosition()
             : text_end_position_;
}

int32 TextBox::GetNonCollapsibleTextStartPosition() const {
  return text_has_leading_white_space_ ? text_start_position_ + 1
                                       : text_start_position_;
}

int32 TextBox::GetNonCollapsibleTextEndPosition() const {
  return text_has_trailing_white_space_ ? text_end_position_ - 1
                                        : text_end_position_;
}

int32 TextBox::GetNonCollapsibleTextLength() const {
  return GetNonCollapsibleTextEndPosition() -
         GetNonCollapsibleTextStartPosition();
}

bool TextBox::HasNonCollapsibleText() const {
  return GetNonCollapsibleTextLength() > 0;
}

std::string TextBox::GetNonCollapsibleText() const {
  return paragraph_->RetrieveUtf8SubString(GetNonCollapsibleTextStartPosition(),
                                           GetNonCollapsibleTextEndPosition(),
                                           Paragraph::kVisualTextOrder);
}

int32 TextBox::GetVisibleTextStartPosition() const {
  return std::max(GetNonCollapsedTextStartPosition(),
                  truncated_text_start_position_);
}

int32 TextBox::GetVisibleTextEndPosition() const {
  return std::min(GetNonCollapsedTextEndPosition(),
                  truncated_text_end_position_);
}

int32 TextBox::GetVisibleTextLength() const {
  return GetVisibleTextEndPosition() - GetVisibleTextStartPosition();
}

bool TextBox::HasVisibleText() const { return GetVisibleTextLength() > 0; }

std::string TextBox::GetVisibleText() const {
  return paragraph_->RetrieveUtf8SubString(GetVisibleTextStartPosition(),
                                           GetVisibleTextEndPosition(),
                                           Paragraph::kVisualTextOrder);
}

}  // namespace layout
}  // namespace cobalt
