// Copyright 2014 Google Inc. 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_end_position_(text_end_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; }

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_end_position_ = truncated_text_end_position_;
  truncated_text_end_position_ = text_end_position_;
}

void TextBox::DoPostEllipsisPlacementProcessing() {
  if (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 {
  DCHECK(baseline_offset_from_top_);
  return *baseline_offset_from_top_;
}

namespace {
void PopulateBaseStyleForTextNode(
    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
    const scoped_refptr<cssom::CSSComputedStyleData>& 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) 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 = GetNonCollapsedTextStartPosition();
      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 COBALT_BOX_DUMP_ENABLED

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  // COBALT_BOX_DUMP_ENABLED

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) {
    truncated_text_end_position_ = text_start_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(
          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;
    }
    truncated_text_end_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);
    truncated_text_end_position_ = text_start_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;
  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(
              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;
    }
    default:
      NOTREACHED();
      wrap_position = -1;
  }
  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::GetVisibleTextEndPosition() const {
  return std::min(GetNonCollapsedTextEndPosition(),
                  truncated_text_end_position_);
}

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

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

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

}  // namespace layout
}  // namespace cobalt
