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

#include "ui/gfx/render_text.h"

#include <limits.h>

#include <algorithm>
#include <climits>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "base/numerics/ranges.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_shader.h"
#include "third_party/icu/source/common/unicode/rbbi.h"
#include "third_party/icu/source/common/unicode/utf16.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "third_party/skia/include/core/SkFontStyle.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/platform_font.h"
#include "ui/gfx/render_text_harfbuzz.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"

#if defined(OS_MACOSX)
#include "third_party/skia/include/ports/SkTypeface_mac.h"
#include "ui/gfx/render_text_mac.h"
#endif  // defined(OS_MACOSX)

namespace gfx {

namespace {

// Default color used for the text and cursor.
const SkColor kDefaultColor = SK_ColorBLACK;

// Default color used for drawing selection background.
const SkColor kDefaultSelectionBackgroundColor = SK_ColorGRAY;

// Fraction of the text size to raise the center of a strike-through line above
// the baseline.
const SkScalar kStrikeThroughOffset = (SK_Scalar1 * 65 / 252);
// Fraction of the text size to lower an underline below the baseline.
const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
// Default fraction of the text size to use for a strike-through or underline.
const SkScalar kLineThicknessFactor = (SK_Scalar1 / 18);

// Invalid value of baseline.  Assigning this value to |baseline_| causes
// re-calculation of baseline.
const int kInvalidBaseline = INT_MAX;

// Given |font| and |display_width|, returns the width of the fade gradient.
int CalculateFadeGradientWidth(const FontList& font_list, int display_width) {
  // Fade in/out about 3 characters of the beginning/end of the string.
  // Use a 1/3 of the display width if the display width is very short.
  const int narrow_width = font_list.GetExpectedTextWidth(3);
  const int gradient_width =
      std::min(narrow_width, gfx::ToRoundedInt(display_width / 3.f));
  DCHECK_GE(gradient_width, 0);
  return gradient_width;
}

// Appends to |positions| and |colors| values corresponding to the fade over
// |fade_rect| from color |c0| to color |c1|.
void AddFadeEffect(const Rect& text_rect,
                   const Rect& fade_rect,
                   SkColor c0,
                   SkColor c1,
                   std::vector<SkScalar>* positions,
                   std::vector<SkColor>* colors) {
  const SkScalar left = static_cast<SkScalar>(fade_rect.x() - text_rect.x());
  const SkScalar width = static_cast<SkScalar>(fade_rect.width());
  const SkScalar p0 = left / text_rect.width();
  const SkScalar p1 = (left + width) / text_rect.width();
  // Prepend 0.0 to |positions|, as required by Skia.
  if (positions->empty() && p0 != 0.0) {
    positions->push_back(0.0);
    colors->push_back(c0);
  }
  positions->push_back(p0);
  colors->push_back(c0);
  positions->push_back(p1);
  colors->push_back(c1);
}

// Creates a SkShader to fade the text, with |left_part| specifying the left
// fade effect, if any, and |right_part| specifying the right fade effect.
sk_sp<cc::PaintShader> CreateFadeShader(const FontList& font_list,
                                        const Rect& text_rect,
                                        const Rect& left_part,
                                        const Rect& right_part,
                                        SkColor color) {
  // The shader should only specify transparency of the fade itself, not the
  // original transparency, which will be applied by the actual renderer.
  DCHECK_EQ(SkColorGetA(color), static_cast<uint8_t>(0xff));

  // In general, fade down to 0 alpha.  But when the available width is less
  // than four characters, linearly ramp up the fade target alpha to as high as
  // 20% at zero width.  This allows the user to see the last faded characters a
  // little better when there are only a few characters shown.
  const float width_fraction =
      text_rect.width() / static_cast<float>(font_list.GetExpectedTextWidth(4));
  const SkAlpha kAlphaAtZeroWidth = 51;
  const SkAlpha alpha =
      (width_fraction < 1)
          ? gfx::ToRoundedInt((1 - width_fraction) * kAlphaAtZeroWidth)
          : 0;
  const SkColor fade_color = SkColorSetA(color, alpha);

  std::vector<SkScalar> positions;
  std::vector<SkColor> colors;

  if (!left_part.IsEmpty())
    AddFadeEffect(text_rect, left_part, fade_color, color,
                  &positions, &colors);
  if (!right_part.IsEmpty())
    AddFadeEffect(text_rect, right_part, color, fade_color,
                  &positions, &colors);
  DCHECK(!positions.empty());

  // Terminate |positions| with 1.0, as required by Skia.
  if (positions.back() != 1.0) {
    positions.push_back(1.0);
    colors.push_back(colors.back());
  }

  const SkPoint points[2] = { PointToSkPoint(text_rect.origin()),
                              PointToSkPoint(text_rect.top_right()) };
  return cc::PaintShader::MakeLinearGradient(
      &points[0], &colors[0], &positions[0], static_cast<int>(colors.size()),
      SkTileMode::kClamp);
}

// Converts a FontRenderParams::Hinting value to the corresponding
// SkFontHinting value.
SkFontHinting FontRenderParamsHintingToSkFontHinting(
    FontRenderParams::Hinting params_hinting) {
  switch (params_hinting) {
    case FontRenderParams::HINTING_NONE:
      return SkFontHinting::kNone;
    case FontRenderParams::HINTING_SLIGHT:
      return SkFontHinting::kSlight;
    case FontRenderParams::HINTING_MEDIUM:
      return SkFontHinting::kNormal;
    case FontRenderParams::HINTING_FULL:
      return SkFontHinting::kFull;
  }
  return SkFontHinting::kNone;
}

// Make sure ranges don't break text graphemes.  If a range in |break_list|
// does break a grapheme in |render_text|, the range will be slightly
// extended to encompass the grapheme.
template <typename T>
void RestoreBreakList(RenderText* render_text, BreakList<T>* break_list) {
  break_list->SetMax(render_text->text().length());
  Range range;
  while (range.end() < break_list->max()) {
    const auto& current_break = break_list->GetBreak(range.end());
    range = break_list->GetRange(current_break);
    if (range.end() < break_list->max() &&
        !render_text->IsValidCursorIndex(range.end())) {
      range.set_end(
          render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD));
      break_list->ApplyValue(current_break->second, range);
    }
  }
}

}  // namespace

namespace internal {

SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas)
    : canvas_(canvas), canvas_skia_(canvas->sk_canvas()) {
  DCHECK(canvas_skia_);
  flags_.setStyle(cc::PaintFlags::kFill_Style);

  font_.setEdging(SkFont::Edging::kSubpixelAntiAlias);
  font_.setSubpixel(true);
  font_.setHinting(SkFontHinting::kNormal);
}

SkiaTextRenderer::~SkiaTextRenderer() {
}

void SkiaTextRenderer::SetDrawLooper(sk_sp<SkDrawLooper> draw_looper) {
  flags_.setLooper(std::move(draw_looper));
}

void SkiaTextRenderer::SetFontRenderParams(const FontRenderParams& params,
                                           bool subpixel_rendering_suppressed) {
  ApplyRenderParams(params, subpixel_rendering_suppressed, &font_);
}

void SkiaTextRenderer::SetTypeface(sk_sp<SkTypeface> typeface) {
  font_.setTypeface(std::move(typeface));
}

void SkiaTextRenderer::SetTextSize(SkScalar size) {
  font_.setSize(size);
}

void SkiaTextRenderer::SetForegroundColor(SkColor foreground) {
  flags_.setColor(foreground);
}

void SkiaTextRenderer::SetShader(sk_sp<cc::PaintShader> shader) {
  flags_.setShader(std::move(shader));
}

void SkiaTextRenderer::DrawPosText(const SkPoint* pos,
                                   const uint16_t* glyphs,
                                   size_t glyph_count) {
  SkTextBlobBuilder builder;
  const auto& run_buffer = builder.allocRunPos(font_, glyph_count);

  static_assert(sizeof(*glyphs) == sizeof(*run_buffer.glyphs), "");
  memcpy(run_buffer.glyphs, glyphs, glyph_count * sizeof(*glyphs));

  static_assert(sizeof(*pos) == 2 * sizeof(*run_buffer.pos), "");
  memcpy(run_buffer.pos, pos, glyph_count * sizeof(*pos));

  canvas_skia_->drawTextBlob(builder.make(), 0, 0, flags_);
}

void SkiaTextRenderer::DrawUnderline(int x,
                                     int y,
                                     int width,
                                     SkScalar thickness_factor) {
  SkScalar x_scalar = SkIntToScalar(x);
  const SkScalar text_size = font_.getSize();
  SkRect r = SkRect::MakeLTRB(
      x_scalar, y + text_size * kUnderlineOffset, x_scalar + width,
      y + (text_size *
           (kUnderlineOffset + (thickness_factor * kLineThicknessFactor))));
  canvas_skia_->drawRect(r, flags_);
}

void SkiaTextRenderer::DrawStrike(int x,
                                  int y,
                                  int width,
                                  SkScalar thickness_factor) {
  const SkScalar text_size = font_.getSize();
  const SkScalar height = text_size * thickness_factor;
  const SkScalar top = y - text_size * kStrikeThroughOffset - height / 2;
  SkScalar x_scalar = SkIntToScalar(x);
  const SkRect r =
      SkRect::MakeLTRB(x_scalar, top, x_scalar + width, top + height);
  canvas_skia_->drawRect(r, flags_);
}

StyleIterator::StyleIterator(const BreakList<SkColor>& colors,
                             const BreakList<BaselineStyle>& baselines,
                             const BreakList<int>& font_size_overrides,
                             const BreakList<Font::Weight>& weights,
                             const std::vector<BreakList<bool>>& styles)
    : colors_(colors),
      baselines_(baselines),
      font_size_overrides_(font_size_overrides),
      weights_(weights),
      styles_(styles) {
  color_ = colors_.breaks().begin();
  baseline_ = baselines_.breaks().begin();
  font_size_override_ = font_size_overrides_.breaks().begin();
  weight_ = weights_.breaks().begin();
  for (size_t i = 0; i < styles_.size(); ++i)
    style_.push_back(styles_[i].breaks().begin());
}

StyleIterator::~StyleIterator() {}

Range StyleIterator::GetRange() const {
  Range range(colors_.GetRange(color_));
  range = range.Intersect(baselines_.GetRange(baseline_));
  range = range.Intersect(font_size_overrides_.GetRange(font_size_override_));
  range = range.Intersect(weights_.GetRange(weight_));
  for (size_t i = 0; i < TEXT_STYLE_COUNT; ++i)
    range = range.Intersect(styles_[i].GetRange(style_[i]));
  return range;
}

void StyleIterator::UpdatePosition(size_t position) {
  color_ = colors_.GetBreak(position);
  baseline_ = baselines_.GetBreak(position);
  font_size_override_ = font_size_overrides_.GetBreak(position);
  weight_ = weights_.GetBreak(position);
  for (size_t i = 0; i < TEXT_STYLE_COUNT; ++i)
    style_[i] = styles_[i].GetBreak(position);
}

LineSegment::LineSegment() : run(0) {}

LineSegment::~LineSegment() {}

Line::Line() : preceding_heights(0), baseline(0) {}

Line::Line(const Line& other) = default;

Line::~Line() {}

void ApplyRenderParams(const FontRenderParams& params,
                       bool subpixel_rendering_suppressed,
                       SkFont* font) {
  if (!params.antialiasing) {
    font->setEdging(SkFont::Edging::kAlias);
  } else if (subpixel_rendering_suppressed ||
             params.subpixel_rendering ==
                 FontRenderParams::SUBPIXEL_RENDERING_NONE) {
    font->setEdging(SkFont::Edging::kAntiAlias);
  } else {
    font->setEdging(SkFont::Edging::kSubpixelAntiAlias);
  }

  font->setSubpixel(params.subpixel_positioning);
  font->setForceAutoHinting(params.autohinter);
  font->setHinting(FontRenderParamsHintingToSkFontHinting(params.hinting));
}

}  // namespace internal

// static
constexpr base::char16 RenderText::kPasswordReplacementChar;
constexpr bool RenderText::kDragToEndIfOutsideVerticalBounds;

RenderText::~RenderText() {
}

// static
std::unique_ptr<RenderText> RenderText::CreateHarfBuzzInstance() {
  return std::make_unique<RenderTextHarfBuzz>();
}

// static
std::unique_ptr<RenderText> RenderText::CreateFor(Typesetter typesetter) {
#if defined(OS_MACOSX)
  if (typesetter == Typesetter::NATIVE)
    return std::make_unique<RenderTextMac>();

#endif  // defined(OS_MACOSX)
  return CreateHarfBuzzInstance();
}

// static
std::unique_ptr<RenderText> RenderText::CreateInstanceDeprecated() {
  return CreateFor(Typesetter::BROWSER);
}

std::unique_ptr<RenderText> RenderText::CreateInstanceOfSameStyle(
    const base::string16& text) const {
  std::unique_ptr<RenderText> render_text = CreateInstanceOfSameType();
  // |SetText()| must be called before styles are set.
  render_text->SetText(text);
  render_text->SetFontList(font_list_);
  render_text->SetDirectionalityMode(directionality_mode_);
  render_text->SetCursorEnabled(cursor_enabled_);
  render_text->set_truncate_length(truncate_length_);
  render_text->styles_ = styles_;
  render_text->baselines_ = baselines_;
  render_text->font_size_overrides_ = font_size_overrides_;
  render_text->colors_ = colors_;
  render_text->weights_ = weights_;
  return render_text;
}

void RenderText::SetText(const base::string16& text) {
  DCHECK(!composition_range_.IsValid());
  if (text_ == text)
    return;
  text_ = text;
  UpdateStyleLengths();

  // Clear style ranges as they might break new text graphemes and apply
  // the first style to the whole text instead.
  colors_.SetValue(colors_.breaks().begin()->second);
  baselines_.SetValue(baselines_.breaks().begin()->second);
  font_size_overrides_.SetValue(font_size_overrides_.breaks().begin()->second);
  weights_.SetValue(weights_.breaks().begin()->second);
  for (size_t style = 0; style < TEXT_STYLE_COUNT; ++style)
    styles_[style].SetValue(styles_[style].breaks().begin()->second);
  cached_bounds_and_offset_valid_ = false;

  // Reset selection model. SetText should always followed by SetSelectionModel
  // or SetCursorPosition in upper layer.
  SetSelectionModel(SelectionModel());

  // Invalidate the cached text direction if it depends on the text contents.
  if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT)
    text_direction_ = base::i18n::UNKNOWN_DIRECTION;

  obscured_reveal_index_ = -1;
  OnTextAttributeChanged();
}

void RenderText::AppendText(const base::string16& text) {
  text_ += text;
  UpdateStyleLengths();
  cached_bounds_and_offset_valid_ = false;
  obscured_reveal_index_ = -1;
  OnTextAttributeChanged();
}

void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) {
  if (horizontal_alignment_ != alignment) {
    horizontal_alignment_ = alignment;
    display_offset_ = Vector2d();
    cached_bounds_and_offset_valid_ = false;
  }
}

void RenderText::SetFontList(const FontList& font_list) {
  font_list_ = font_list;
  const int font_style = font_list.GetFontStyle();
  weights_.SetValue(font_list.GetFontWeight());
  styles_[TEXT_STYLE_ITALIC].SetValue((font_style & Font::ITALIC) != 0);
  styles_[TEXT_STYLE_UNDERLINE].SetValue((font_style & Font::UNDERLINE) != 0);
  styles_[TEXT_STYLE_HEAVY_UNDERLINE].SetValue(false);
  baseline_ = kInvalidBaseline;
  cached_bounds_and_offset_valid_ = false;
  OnLayoutTextAttributeChanged(false);
}

void RenderText::SetCursorEnabled(bool cursor_enabled) {
  cursor_enabled_ = cursor_enabled;
  cached_bounds_and_offset_valid_ = false;
}

void RenderText::SetObscured(bool obscured) {
  if (obscured != obscured_) {
    obscured_ = obscured;
    obscured_reveal_index_ = -1;
    cached_bounds_and_offset_valid_ = false;
    OnTextAttributeChanged();
  }
}

void RenderText::SetObscuredRevealIndex(int index) {
  if (obscured_reveal_index_ == index)
    return;

  obscured_reveal_index_ = index;
  cached_bounds_and_offset_valid_ = false;
  OnTextAttributeChanged();
}

void RenderText::SetMultiline(bool multiline) {
  if (multiline != multiline_) {
    multiline_ = multiline;
    cached_bounds_and_offset_valid_ = false;
    lines_.clear();
    OnTextAttributeChanged();
  }
}

void RenderText::SetMaxLines(size_t max_lines) {
  max_lines_ = max_lines;
  OnDisplayTextAttributeChanged();
}

size_t RenderText::GetNumLines() {
  return lines_.size();
}

void RenderText::SetWordWrapBehavior(WordWrapBehavior behavior) {
  if (word_wrap_behavior_ == behavior)
    return;
  word_wrap_behavior_ = behavior;
  if (multiline_) {
    cached_bounds_and_offset_valid_ = false;
    lines_.clear();
    OnTextAttributeChanged();
  }
}

void RenderText::SetReplaceNewlineCharsWithSymbols(bool replace) {
  if (replace_newline_chars_with_symbols_ == replace)
    return;
  replace_newline_chars_with_symbols_ = replace;
  cached_bounds_and_offset_valid_ = false;
  OnTextAttributeChanged();
}

void RenderText::SetMinLineHeight(int line_height) {
  if (min_line_height_ == line_height)
    return;
  min_line_height_ = line_height;
  cached_bounds_and_offset_valid_ = false;
  lines_.clear();
  OnDisplayTextAttributeChanged();
}

void RenderText::SetElideBehavior(ElideBehavior elide_behavior) {
  // TODO(skanuj) : Add a test for triggering layout change.
  if (elide_behavior_ != elide_behavior) {
    elide_behavior_ = elide_behavior;
    OnDisplayTextAttributeChanged();
  }
}

void RenderText::SetDisplayRect(const Rect& r) {
  if (r != display_rect_) {
    display_rect_ = r;
    baseline_ = kInvalidBaseline;
    cached_bounds_and_offset_valid_ = false;
    lines_.clear();
    if (elide_behavior_ != NO_ELIDE &&
        elide_behavior_ != FADE_TAIL) {
      OnDisplayTextAttributeChanged();
    }
  }
}

void RenderText::SetCursorPosition(size_t position) {
  size_t cursor = std::min(position, text().length());
  if (IsValidCursorIndex(cursor)) {
    SetSelectionModel(SelectionModel(
        cursor, (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD));
  }
}

void RenderText::MoveCursor(BreakType break_type,
                            VisualCursorDirection direction,
                            SelectionBehavior selection_behavior) {
  SelectionModel cursor(cursor_position(), selection_model_.caret_affinity());

  // Ensure |cursor| is at the "end" of the current selection, since this
  // determines which side should grow or shrink. If the prior change to the
  // selection wasn't from cursor movement, the selection may be undirected. Or,
  // the selection may be collapsing. In these cases, pick the "end" using
  // |direction| (e.g. the arrow key) rather than the current selection range.
  if ((!has_directed_selection_ || selection_behavior == SELECTION_NONE) &&
      !selection().is_empty()) {
    SelectionModel start = GetSelectionModelForSelectionStart();
    int start_x = GetCursorBounds(start, true).x();
    int end_x = GetCursorBounds(cursor, true).x();

    // Use the selection start if it is left (when |direction| is CURSOR_LEFT)
    // or right (when |direction| is CURSOR_RIGHT) of the selection end.
    if (direction == CURSOR_RIGHT ? start_x > end_x : start_x < end_x) {
      // In this case, a direction has been chosen that doesn't match
      // |selection_model|, so the range must be reversed to place the cursor at
      // the other end. Note the affinity won't matter: only the affinity of
      // |start| (which points "in" to the selection) determines the movement.
      Range range = selection_model_.selection();
      selection_model_ = SelectionModel(Range(range.end(), range.start()),
                                        selection_model_.caret_affinity());
      cursor = start;
    }
  }

  // Cancelling a selection moves to the edge of the selection.
  if (break_type != LINE_BREAK && !selection().is_empty() &&
      selection_behavior == SELECTION_NONE) {
    // Use the nearest word boundary in the proper |direction| for word breaks.
    if (break_type == WORD_BREAK)
      cursor = GetAdjacentSelectionModel(cursor, break_type, direction);
    // Use an adjacent selection model if the cursor is not at a valid position.
    if (!IsValidCursorIndex(cursor.caret_pos()))
      cursor = GetAdjacentSelectionModel(cursor, CHARACTER_BREAK, direction);
  } else {
    cursor = GetAdjacentSelectionModel(cursor, break_type, direction);
  }

  // |cursor| corresponds to the tentative end point of the new selection. The
  // selection direction is reversed iff the current selection is non-empty and
  // the old selection end point and |cursor| are at the opposite ends of the
  // old selection start point.
  uint32_t min_end = std::min(selection().end(), cursor.selection().end());
  uint32_t max_end = std::max(selection().end(), cursor.selection().end());
  uint32_t current_start = selection().start();

  bool selection_reversed = !selection().is_empty() &&
                            min_end <= current_start &&
                            current_start <= max_end;

  // Take |selection_behavior| into account.
  switch (selection_behavior) {
    case SELECTION_RETAIN:
      cursor.set_selection_start(current_start);
      break;
    case SELECTION_EXTEND:
      cursor.set_selection_start(selection_reversed ? selection().end()
                                                    : current_start);
      break;
    case SELECTION_CARET:
      if (selection_reversed) {
        cursor =
            SelectionModel(current_start, selection_model_.caret_affinity());
      } else {
        cursor.set_selection_start(current_start);
      }
      break;
    case SELECTION_NONE:
      // Do nothing.
      break;
  }

  SetSelection(cursor);
  has_directed_selection_ = true;
}

bool RenderText::SetSelection(const SelectionModel& model) {
  // Enforce valid selection model components.
  size_t text_length = text().length();
  Range range(
      std::min(model.selection().start(), static_cast<uint32_t>(text_length)),
      std::min(model.caret_pos(), text_length));
  // The current model only supports caret positions at valid cursor indices.
  if (!IsValidCursorIndex(range.start()) || !IsValidCursorIndex(range.end()))
    return false;
  SelectionModel sel(range, model.caret_affinity());
  bool changed = sel != selection_model_;
  SetSelectionModel(sel);
  return changed;
}

bool RenderText::MoveCursorToPoint(const gfx::Point& point,
                                   bool select,
                                   const gfx::Point& drag_origin) {
  gfx::SelectionModel model = FindCursorPosition(point, drag_origin);
  if (select)
    model.set_selection_start(selection().start());
  return SetSelection(model);
}

bool RenderText::SelectRange(const Range& range) {
  uint32_t text_length = static_cast<uint32_t>(text().length());
  Range sel(std::min(range.start(), text_length),
            std::min(range.end(), text_length));
  // Allow selection bounds at valid indicies amid multi-character graphemes.
  if (!IsValidLogicalIndex(sel.start()) || !IsValidLogicalIndex(sel.end()))
    return false;
  LogicalCursorDirection affinity =
      (sel.is_reversed() || sel.is_empty()) ? CURSOR_FORWARD : CURSOR_BACKWARD;
  SetSelectionModel(SelectionModel(sel, affinity));
  return true;
}

bool RenderText::IsPointInSelection(const Point& point) {
  if (selection().is_empty())
    return false;
  SelectionModel cursor = FindCursorPosition(point);
  return RangeContainsCaret(
      selection(), cursor.caret_pos(), cursor.caret_affinity());
}

void RenderText::ClearSelection() {
  SetSelectionModel(
      SelectionModel(cursor_position(), selection_model_.caret_affinity()));
}

void RenderText::SelectAll(bool reversed) {
  const size_t length = text().length();
  const Range all = reversed ? Range(length, 0) : Range(0, length);
  const bool success = SelectRange(all);
  DCHECK(success);
}

void RenderText::SelectWord() {
  SelectRange(ExpandRangeToWordBoundary(selection()));
}

void RenderText::SetCompositionRange(const Range& composition_range) {
  CHECK(!composition_range.IsValid() ||
        Range(0, text_.length()).Contains(composition_range));
  composition_range_.set_end(composition_range.end());
  composition_range_.set_start(composition_range.start());
  // TODO(oshima|msw): Altering composition underlines shouldn't
  // require layout changes. It's currently necessary because
  // RenderTextHarfBuzz paints text decorations by run, and
  // RenderTextMac applies all styles during layout.
  OnLayoutTextAttributeChanged(false);
}

void RenderText::SetColor(SkColor value) {
  colors_.SetValue(value);
  OnTextColorChanged();
}

void RenderText::ApplyColor(SkColor value, const Range& range) {
  colors_.ApplyValue(value, range);
  OnTextColorChanged();
}

void RenderText::SetBaselineStyle(BaselineStyle value) {
  baselines_.SetValue(value);
}

void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) {
  baselines_.ApplyValue(value, range);
}

void RenderText::ApplyFontSizeOverride(int font_size_override,
                                       const Range& range) {
  font_size_overrides_.ApplyValue(font_size_override, range);
}

void RenderText::SetStyle(TextStyle style, bool value) {
  styles_[style].SetValue(value);

  cached_bounds_and_offset_valid_ = false;
  // TODO(oshima|msw): Not all style change requires layout changes.
  // Consider optimizing based on the type of change.
  OnLayoutTextAttributeChanged(false);
}

void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) {
  // Do not change styles mid-grapheme to avoid breaking ligatures.
  const size_t start = IsValidCursorIndex(range.start()) ? range.start() :
      IndexOfAdjacentGrapheme(range.start(), CURSOR_BACKWARD);
  const size_t end = IsValidCursorIndex(range.end()) ? range.end() :
      IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD);
  styles_[style].ApplyValue(value, Range(start, end));

  cached_bounds_and_offset_valid_ = false;
  // TODO(oshima|msw): Not all style change requires layout changes.
  // Consider optimizing based on the type of change.
  OnLayoutTextAttributeChanged(false);
}

void RenderText::SetWeight(Font::Weight weight) {
  weights_.SetValue(weight);

  cached_bounds_and_offset_valid_ = false;
  OnLayoutTextAttributeChanged(false);
}

void RenderText::ApplyWeight(Font::Weight weight, const Range& range) {
  weights_.ApplyValue(weight, range);

  cached_bounds_and_offset_valid_ = false;
  OnLayoutTextAttributeChanged(false);
}

bool RenderText::GetStyle(TextStyle style) const {
  return (styles_[style].breaks().size() == 1) &&
         styles_[style].breaks().front().second;
}

void RenderText::SetDirectionalityMode(DirectionalityMode mode) {
  if (mode == directionality_mode_)
    return;

  directionality_mode_ = mode;
  text_direction_ = base::i18n::UNKNOWN_DIRECTION;
  cached_bounds_and_offset_valid_ = false;
  OnLayoutTextAttributeChanged(false);
}

base::i18n::TextDirection RenderText::GetDisplayTextDirection() {
  return GetTextDirection(GetDisplayText());
}

VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() {
  return GetDisplayTextDirection() == base::i18n::LEFT_TO_RIGHT ? CURSOR_RIGHT
                                                                : CURSOR_LEFT;
}

VisualCursorDirection RenderText::GetVisualDirectionOfLogicalBeginning() {
  return GetDisplayTextDirection() == base::i18n::RIGHT_TO_LEFT ? CURSOR_RIGHT
                                                                : CURSOR_LEFT;
}

SizeF RenderText::GetStringSizeF() {
  return SizeF(GetStringSize());
}

float RenderText::GetContentWidthF() {
  const float string_size = GetStringSizeF().width();
  // The cursor is drawn one pixel beyond the int-enclosed text bounds.
  return cursor_enabled_ ? std::ceil(string_size) + 1 : string_size;
}

int RenderText::GetContentWidth() {
  return ToCeiledInt(GetContentWidthF());
}

int RenderText::GetBaseline() {
  if (baseline_ == kInvalidBaseline) {
    baseline_ =
        DetermineBaselineCenteringText(display_rect().height(), font_list());
  }
  DCHECK_NE(kInvalidBaseline, baseline_);
  return baseline_;
}

void RenderText::Draw(Canvas* canvas) {
  EnsureLayout();

  if (clip_to_display_rect()) {
    Rect clip_rect(display_rect());
    clip_rect.Inset(ShadowValue::GetMargin(shadows_));

    canvas->Save();
    canvas->ClipRect(clip_rect);
  }

  if (!text().empty() && focused())
    DrawSelection(canvas);

  if (!text().empty()) {
    internal::SkiaTextRenderer renderer(canvas);
    DrawVisualText(&renderer);
  }

  if (clip_to_display_rect())
    canvas->Restore();
}

bool RenderText::IsValidLogicalIndex(size_t index) const {
  // Check that the index is at a valid code point (not mid-surrgate-pair) and
  // that it's not truncated from the display text (its glyph may be shown).
  //
  // Indices within truncated text are disallowed so users can easily interact
  // with the underlying truncated text using the ellipsis as a proxy. This lets
  // users select all text, select the truncated text, and transition from the
  // last rendered glyph to the end of the text without getting invisible cursor
  // positions nor needing unbounded arrow key presses to traverse the ellipsis.
  return index == 0 || index == text().length() ||
      (index < text().length() &&
       (truncate_length_ == 0 || index < truncate_length_) &&
       IsValidCodePointIndex(text(), index));
}

Rect RenderText::GetCursorBounds(const SelectionModel& caret,
                                 bool insert_mode) {
  // TODO(ckocagil): Support multiline. This function should return the height
  //                 of the line the cursor is on. |GetStringSize()| now returns
  //                 the multiline size, eliminate its use here.
  DCHECK(!multiline_);
  EnsureLayout();
  size_t caret_pos = caret.caret_pos();
  DCHECK(IsValidLogicalIndex(caret_pos));
  // In overtype mode, ignore the affinity and always indicate that we will
  // overtype the next character.
  LogicalCursorDirection caret_affinity =
      insert_mode ? caret.caret_affinity() : CURSOR_FORWARD;
  int x = 0, width = 1;
  Size size = GetStringSize();

  // Check whether the caret is attached to a boundary. Always return a 1-dip
  // width caret at the boundary. Avoid calling IndexOfAdjacentGrapheme(), since
  // it is slow and can impact browser startup here.
  // In insert mode, index 0 is always a boundary. The end, however, is not at a
  // boundary when the string ends in RTL text and there is LTR text around it.
  const bool at_boundary =
      (insert_mode && caret_pos == 0) ||
      caret_pos == (caret_affinity == CURSOR_BACKWARD ? 0 : text().length());
  if (at_boundary) {
    const bool rtl = GetDisplayTextDirection() == base::i18n::RIGHT_TO_LEFT;
    if (rtl == (caret_pos == 0))
      x = size.width();
  } else {
    // Find the next grapheme continuing in the current direction. This
    // determines the substring range that should be highlighted.
    size_t caret_end = IndexOfAdjacentGrapheme(caret_pos, caret_affinity);
    if (caret_end < caret_pos)
      std::swap(caret_end, caret_pos);
    const Range xspan = GetCursorSpan(Range(caret_pos, caret_end));
    if (insert_mode) {
      x = (caret_affinity == CURSOR_BACKWARD) ? xspan.end() : xspan.start();
    } else {  // overtype mode
      x = xspan.GetMin();
      width = xspan.length();
    }
  }
  return Rect(ToViewPoint(Point(x, 0)), Size(width, size.height()));
}

const Rect& RenderText::GetUpdatedCursorBounds() {
  UpdateCachedBoundsAndOffset();
  return cursor_bounds_;
}

size_t RenderText::IndexOfAdjacentGrapheme(size_t index,
                                           LogicalCursorDirection direction) {
  if (index > text().length())
    return text().length();

  EnsureLayout();

  if (direction == CURSOR_FORWARD) {
    while (index < text().length()) {
      index++;
      if (IsValidCursorIndex(index))
        return index;
    }
    return text().length();
  }

  while (index > 0) {
    index--;
    if (IsValidCursorIndex(index))
      return index;
  }
  return 0;
}

SelectionModel RenderText::GetSelectionModelForSelectionStart() const {
  const Range& sel = selection();
  if (sel.is_empty())
    return selection_model_;
  return SelectionModel(sel.start(),
                        sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD);
}

RectF RenderText::GetStringRect() {
  return RectF(PointF(ToViewPoint(Point())), GetStringSizeF());
}

const Vector2d& RenderText::GetUpdatedDisplayOffset() {
  UpdateCachedBoundsAndOffset();
  return display_offset_;
}

void RenderText::SetDisplayOffset(int horizontal_offset) {
  const int extra_content = GetContentWidth() - display_rect_.width();
  const int cursor_width = cursor_enabled_ ? 1 : 0;

  int min_offset = 0;
  int max_offset = 0;
  if (extra_content > 0) {
    switch (GetCurrentHorizontalAlignment()) {
      case ALIGN_LEFT:
        min_offset = -extra_content;
        break;
      case ALIGN_RIGHT:
        max_offset = extra_content;
        break;
      case ALIGN_CENTER:
        // The extra space reserved for cursor at the end of the text is ignored
        // when centering text. So, to calculate the valid range for offset, we
        // exclude that extra space, calculate the range, and add it back to the
        // range (if cursor is enabled).
        min_offset = -(extra_content - cursor_width + 1) / 2 - cursor_width;
        max_offset = (extra_content - cursor_width) / 2;
        break;
      default:
        break;
    }
  }
  if (horizontal_offset < min_offset)
    horizontal_offset = min_offset;
  else if (horizontal_offset > max_offset)
    horizontal_offset = max_offset;

  cached_bounds_and_offset_valid_ = true;
  display_offset_.set_x(horizontal_offset);
  cursor_bounds_ = GetCursorBounds(selection_model_, true);
}

Vector2d RenderText::GetLineOffset(size_t line_number) {
  EnsureLayout();
  Vector2d offset = display_rect().OffsetFromOrigin();
  // TODO(ckocagil): Apply the display offset for multiline scrolling.
  if (!multiline()) {
    offset.Add(GetUpdatedDisplayOffset());
  } else {
    DCHECK_LT(line_number, lines().size());
    offset.Add(Vector2d(0, lines_[line_number].preceding_heights));
  }
  offset.Add(GetAlignmentOffset(line_number));
  return offset;
}

bool RenderText::GetWordLookupDataAtPoint(const Point& point,
                                          DecoratedText* decorated_word,
                                          Point* baseline_point) {
  if (obscured())
    return false;

  EnsureLayout();
  const SelectionModel model_at_point = FindCursorPosition(point);
  const size_t word_index =
      GetNearestWordStartBoundary(model_at_point.caret_pos());
  if (word_index >= text().length())
    return false;

  const Range word_range = ExpandRangeToWordBoundary(Range(word_index));
  DCHECK(!word_range.is_reversed());
  DCHECK(!word_range.is_empty());

  return GetLookupDataForRange(word_range, decorated_word, baseline_point);
}

bool RenderText::GetLookupDataForRange(const Range& range,
                                       DecoratedText* decorated_text,
                                       Point* baseline_point) {
  EnsureLayout();

  const std::vector<Rect> word_bounds = GetSubstringBounds(range);
  if (word_bounds.empty() || !GetDecoratedTextForRange(range, decorated_text)) {
    return false;
  }

  // Retrieve the baseline origin of the left-most glyph.
  const auto left_rect = std::min_element(
      word_bounds.begin(), word_bounds.end(),
      [](const Rect& lhs, const Rect& rhs) { return lhs.x() < rhs.x(); });
  const int line_index = GetLineContainingYCoord(left_rect->CenterPoint().y() -
                                                 GetLineOffset(0).y());
  if (line_index < 0 || line_index >= static_cast<int>(lines().size()))
    return false;
  *baseline_point =
      left_rect->origin() + Vector2d(0, lines()[line_index].baseline);
  return true;
}

base::string16 RenderText::GetTextFromRange(const Range& range) const {
  if (range.IsValid() && range.GetMin() < text().length())
    return text().substr(range.GetMin(), range.length());
  return base::string16();
}

RenderText::RenderText()
    : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT),
      directionality_mode_(DIRECTIONALITY_FROM_TEXT),
      text_direction_(base::i18n::UNKNOWN_DIRECTION),
      cursor_enabled_(true),
      has_directed_selection_(kSelectionIsAlwaysDirected),
      selection_color_(kDefaultColor),
      selection_background_focused_color_(kDefaultSelectionBackgroundColor),
      focused_(false),
      composition_range_(Range::InvalidRange()),
      colors_(kDefaultColor),
      baselines_(NORMAL_BASELINE),
      font_size_overrides_(0),
      weights_(Font::Weight::NORMAL),
      styles_(TEXT_STYLE_COUNT),
      composition_and_selection_styles_applied_(false),
      obscured_(false),
      obscured_reveal_index_(-1),
      truncate_length_(0),
      elide_behavior_(NO_ELIDE),
      text_elided_(false),
      min_line_height_(0),
      multiline_(false),
      max_lines_(0),
      word_wrap_behavior_(IGNORE_LONG_WORDS),
      replace_newline_chars_with_symbols_(true),
      subpixel_rendering_suppressed_(false),
      clip_to_display_rect_(true),
      baseline_(kInvalidBaseline),
      cached_bounds_and_offset_valid_(false),
      strike_thickness_factor_(kLineThicknessFactor) {}

bool RenderText::IsHomogeneous() const {
  if (colors().breaks().size() > 1 || baselines().breaks().size() > 1 ||
      font_size_overrides().breaks().size() > 1 ||
      weights().breaks().size() > 1)
    return false;
  for (size_t style = 0; style < TEXT_STYLE_COUNT; ++style) {
    if (styles()[style].breaks().size() > 1)
      return false;
  }
  return true;
}

SelectionModel RenderText::GetAdjacentSelectionModel(
    const SelectionModel& current,
    BreakType break_type,
    VisualCursorDirection direction) {
  EnsureLayout();

  if (break_type == LINE_BREAK || text().empty())
    return EdgeSelectionModel(direction);
  if (break_type == CHARACTER_BREAK)
    return AdjacentCharSelectionModel(current, direction);
  DCHECK(break_type == WORD_BREAK);
  return AdjacentWordSelectionModel(current, direction);
}

SelectionModel RenderText::EdgeSelectionModel(
    VisualCursorDirection direction) {
  if (direction == GetVisualDirectionOfLogicalEnd())
    return SelectionModel(text().length(), CURSOR_FORWARD);
  return SelectionModel(0, CURSOR_BACKWARD);
}

SelectionModel RenderText::LineSelectionModel(size_t line_index,
                                              VisualCursorDirection direction) {
  const internal::Line& line = lines()[line_index];
  if (line.segments.empty()) {
    // Only the last line can be empty.
    DCHECK_EQ(lines().size() - 1, line_index);
    return EdgeSelectionModel(GetVisualDirectionOfLogicalEnd());
  }

  size_t max_index = 0;
  size_t min_index = text().length();
  for (const auto& segment : line.segments) {
    min_index = std::min<size_t>(min_index, segment.char_range.GetMin());
    max_index = std::max<size_t>(max_index, segment.char_range.GetMax());
  }

  return direction == GetVisualDirectionOfLogicalEnd()
             ? SelectionModel(DisplayIndexToTextIndex(max_index),
                              CURSOR_FORWARD)
             : SelectionModel(DisplayIndexToTextIndex(min_index),
                              CURSOR_BACKWARD);
}

void RenderText::SetSelectionModel(const SelectionModel& model) {
  DCHECK_LE(model.selection().GetMax(), text().length());
  selection_model_ = model;
  cached_bounds_and_offset_valid_ = false;
  has_directed_selection_ = kSelectionIsAlwaysDirected;
}

void RenderText::OnTextColorChanged() {
}

void RenderText::UpdateDisplayText(float text_width) {
  // TODO(krb): Consider other elision modes for multiline.
  if ((multiline_ && (!max_lines_ || elide_behavior() != ELIDE_TAIL)) ||
      elide_behavior() == NO_ELIDE || elide_behavior() == FADE_TAIL ||
      (text_width > 0 && text_width < display_rect_.width()) ||
      layout_text_.empty()) {
    text_elided_ = false;
    display_text_.clear();
    return;
  }

  if (!multiline_) {
    // This doesn't trim styles so ellipsis may get rendered as a different
    // style than the preceding text. See crbug.com/327850.
    display_text_.assign(Elide(layout_text_, text_width,
                               static_cast<float>(display_rect_.width()),
                               elide_behavior_));
  } else {
    bool was_elided = text_elided_;
    text_elided_ = false;
    display_text_.clear();

    std::unique_ptr<RenderText> render_text(
        CreateInstanceOfSameStyle(layout_text_));
    render_text->SetMultiline(true);
    render_text->SetWordWrapBehavior(word_wrap_behavior_);
    render_text->SetDisplayRect(display_rect_);
    // Have it arrange words on |lines_|.
    render_text->EnsureLayout();

    if (render_text->lines_.size() > max_lines_) {
      size_t start_of_elision = render_text->lines_[max_lines_ - 1]
                                    .segments.front()
                                    .char_range.start();
      base::string16 text_to_elide = layout_text_.substr(start_of_elision);
      display_text_.assign(layout_text_.substr(0, start_of_elision) +
                           Elide(text_to_elide, 0,
                                 static_cast<float>(display_rect_.width()),
                                 ELIDE_TAIL));
      // Have GetLineBreaks() re-calculate.
      line_breaks_.SetMax(0);
    } else {
      // If elision changed, re-calculate.
      if (was_elided)
        line_breaks_.SetMax(0);
      // Initial state above is fine.
      return;
    }
  }
  text_elided_ = display_text_ != layout_text_;
  if (!text_elided_)
    display_text_.clear();
}

const BreakList<size_t>& RenderText::GetLineBreaks() {
  if (line_breaks_.max() != 0)
    return line_breaks_;

  const base::string16& layout_text = GetDisplayText();
  const size_t text_length = layout_text.length();
  line_breaks_.SetValue(0);
  line_breaks_.SetMax(text_length);
  base::i18n::BreakIterator iter(layout_text,
                                 base::i18n::BreakIterator::BREAK_LINE);
  const bool success = iter.Init();
  DCHECK(success);
  if (success) {
    do {
      line_breaks_.ApplyValue(iter.pos(), Range(iter.pos(), text_length));
    } while (iter.Advance());
  }
  return line_breaks_;
}

void RenderText::ApplyCompositionAndSelectionStyles() {
  // Save the underline and color breaks to undo the temporary styles later.
  DCHECK(!composition_and_selection_styles_applied_);
  saved_colors_ = colors_;
  saved_underlines_ = styles_[TEXT_STYLE_HEAVY_UNDERLINE];

  // Apply an underline to the composition range in |underlines|.
  if (composition_range_.IsValid() && !composition_range_.is_empty())
    styles_[TEXT_STYLE_HEAVY_UNDERLINE].ApplyValue(true, composition_range_);

  // Apply the selected text color to the [un-reversed] selection range.
  if (!selection().is_empty() && focused()) {
    const Range range(selection().GetMin(), selection().GetMax());
    colors_.ApplyValue(selection_color_, range);
  }
  composition_and_selection_styles_applied_ = true;
}

void RenderText::UndoCompositionAndSelectionStyles() {
  // Restore the underline and color breaks to undo the temporary styles.
  DCHECK(composition_and_selection_styles_applied_);
  colors_ = saved_colors_;
  styles_[TEXT_STYLE_HEAVY_UNDERLINE] = saved_underlines_;
  composition_and_selection_styles_applied_ = false;
}

Point RenderText::ToViewPoint(const Point& point) {
  if (!multiline())
    return point + GetLineOffset(0);

  // TODO(ckocagil): Traverse individual line segments for RTL support.
  DCHECK(!lines_.empty());
  int x = point.x();
  size_t line = 0;
  for (; line < lines_.size() && x > lines_[line].size.width(); ++line)
    x -= lines_[line].size.width();

  // If |point| is outside the text space, clip it to the end of the last line.
  if (line == lines_.size())
    x = lines_[--line].size.width();
  return Point(x, point.y()) + GetLineOffset(line);
}

HorizontalAlignment RenderText::GetCurrentHorizontalAlignment() {
  if (horizontal_alignment_ != ALIGN_TO_HEAD)
    return horizontal_alignment_;
  return GetDisplayTextDirection() == base::i18n::RIGHT_TO_LEFT ?
      ALIGN_RIGHT : ALIGN_LEFT;
}

Vector2d RenderText::GetAlignmentOffset(size_t line_number) {
  // TODO(ckocagil): Enable |lines_| usage on RenderTextMac.
  if (MultilineSupported() && multiline_)
    DCHECK_LT(line_number, lines_.size());
  Vector2d offset;
  HorizontalAlignment horizontal_alignment = GetCurrentHorizontalAlignment();
  if (horizontal_alignment != ALIGN_LEFT) {
    const int width = multiline_ ?
        std::ceil(lines_[line_number].size.width()) +
        (cursor_enabled_ ? 1 : 0) :
        GetContentWidth();
    offset.set_x(display_rect().width() - width);
    // Put any extra margin pixel on the left to match legacy behavior.
    if (horizontal_alignment == ALIGN_CENTER)
      offset.set_x((offset.x() + 1) / 2);
  }

  // Vertically center the text.
  if (multiline_) {
    const int text_height = lines_.back().preceding_heights +
        lines_.back().size.height();
    offset.set_y((display_rect_.height() - text_height) / 2);
  } else {
    offset.set_y(GetBaseline() - GetDisplayTextBaseline());
  }

  return offset;
}

void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) {
  const int width = display_rect().width();
  if (multiline() || elide_behavior_ != FADE_TAIL || GetContentWidth() <= width)
    return;

  const int gradient_width = CalculateFadeGradientWidth(font_list(), width);
  if (gradient_width == 0)
    return;

  HorizontalAlignment horizontal_alignment = GetCurrentHorizontalAlignment();
  Rect solid_part = display_rect();
  Rect left_part;
  Rect right_part;
  if (horizontal_alignment != ALIGN_LEFT) {
    left_part = solid_part;
    left_part.Inset(0, 0, solid_part.width() - gradient_width, 0);
    solid_part.Inset(gradient_width, 0, 0, 0);
  }
  if (horizontal_alignment != ALIGN_RIGHT) {
    right_part = solid_part;
    right_part.Inset(solid_part.width() - gradient_width, 0, 0, 0);
    solid_part.Inset(0, 0, gradient_width, 0);
  }

  // CreateFadeShader() expects at least one part to not be empty.
  // See https://crbug.com/706835.
  if (left_part.IsEmpty() && right_part.IsEmpty())
    return;

  Rect text_rect = display_rect();
  text_rect.Inset(GetAlignmentOffset(0).x(), 0, 0, 0);

  // TODO(msw): Use the actual text colors corresponding to each faded part.
  renderer->SetShader(
      CreateFadeShader(font_list(), text_rect, left_part, right_part,
                       SkColorSetA(colors_.breaks().front().second, 0xff)));
}

void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) {
  renderer->SetDrawLooper(CreateShadowDrawLooper(shadows_));
}

base::i18n::TextDirection RenderText::GetTextDirection(
    const base::string16& text) {
  if (text_direction_ == base::i18n::UNKNOWN_DIRECTION) {
    switch (directionality_mode_) {
      case DIRECTIONALITY_FROM_TEXT:
        // Derive the direction from the display text, which differs from text()
        // in the case of obscured (password) textfields.
        text_direction_ =
            base::i18n::GetFirstStrongCharacterDirection(text);
        break;
      case DIRECTIONALITY_FROM_UI:
        text_direction_ = base::i18n::IsRTL() ? base::i18n::RIGHT_TO_LEFT :
                                                base::i18n::LEFT_TO_RIGHT;
        break;
      case DIRECTIONALITY_FORCE_LTR:
        text_direction_ = base::i18n::LEFT_TO_RIGHT;
        break;
      case DIRECTIONALITY_FORCE_RTL:
        text_direction_ = base::i18n::RIGHT_TO_LEFT;
        break;
      case DIRECTIONALITY_AS_URL:
        // Rendering as a URL implies left-to-right paragraph direction.
        // URL Standard specifies that a URL "should be rendered as if it were
        // in a left-to-right embedding".
        // https://url.spec.whatwg.org/#url-rendering
        //
        // Consider logical string for domain "ABC.com/hello" (where ABC are
        // Hebrew (RTL) characters). The normal Bidi algorithm renders this as
        // "com/hello.CBA"; by forcing LTR, it is rendered as "CBA.com/hello".
        //
        // Note that this only applies a LTR embedding at the top level; it
        // doesn't change the Bidi algorithm, so there are still some URLs that
        // will render in a confusing order. Consider the logical string
        // "abc.COM/HELLO/world", which will render as "abc.OLLEH/MOC/world".
        // See https://crbug.com/351639.
        //
        // Note that the LeftToRightUrls feature flag enables additional
        // behaviour for DIRECTIONALITY_AS_URL, but the left-to-right embedding
        // behaviour is always enabled, regardless of the flag.
        text_direction_ = base::i18n::LEFT_TO_RIGHT;
        break;
      default:
        NOTREACHED();
    }
  }

  return text_direction_;
}

size_t RenderText::TextIndexToGivenTextIndex(const base::string16& given_text,
                                             size_t index) const {
  DCHECK(given_text == layout_text() || given_text == display_text());
  DCHECK_LE(index, text().length());
  ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index;
  CHECK_GE(i, 0);
  // Clamp indices to the length of the given layout or display text.
  return std::min<size_t>(given_text.length(), i);
}

void RenderText::UpdateStyleLengths() {
  const size_t text_length = text_.length();
  colors_.SetMax(text_length);
  baselines_.SetMax(text_length);
  font_size_overrides_.SetMax(text_length);
  weights_.SetMax(text_length);
  for (size_t style = 0; style < TEXT_STYLE_COUNT; ++style)
    styles_[style].SetMax(text_length);
}

int RenderText::GetLineContainingYCoord(float text_y) {
  if (text_y < 0)
    return -1;

  for (size_t i = 0; i < lines().size(); i++) {
    const internal::Line& line = lines()[i];

    if (text_y <= line.size.height())
      return i;
    text_y -= line.size.height();
  }

  return lines().size();
}

// static
bool RenderText::RangeContainsCaret(const Range& range,
                                    size_t caret_pos,
                                    LogicalCursorDirection caret_affinity) {
  // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9).
  size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ?
      caret_pos - 1 : caret_pos + 1;
  return range.Contains(Range(caret_pos, adjacent));
}

// static
int RenderText::DetermineBaselineCenteringText(const int display_height,
                                               const FontList& font_list) {
  const int font_height = font_list.GetHeight();
  // Lower and upper bound of baseline shift as we try to show as much area of
  // text as possible.  In particular case of |display_height| == |font_height|,
  // we do not want to shift the baseline.
  const int min_shift = std::min(0, display_height - font_height);
  const int max_shift = std::abs(display_height - font_height);
  const int baseline = font_list.GetBaseline();
  const int cap_height = font_list.GetCapHeight();
  const int internal_leading = baseline - cap_height;
  // Some platforms don't support getting the cap height, and simply return
  // the entire font ascent from GetCapHeight().  Centering the ascent makes
  // the font look too low, so if GetCapHeight() returns the ascent, center
  // the entire font height instead.
  const int space =
      display_height - ((internal_leading != 0) ? cap_height : font_height);
  const int baseline_shift = space / 2 - internal_leading;
  return baseline + std::max(min_shift, std::min(max_shift, baseline_shift));
}

// static
gfx::Rect RenderText::ExpandToBeVerticallySymmetric(
    const gfx::Rect& rect,
    const gfx::Rect& display_rect) {
  // Mirror |rect| accross the horizontal line dividing |display_rect| in half.
  gfx::Rect result = rect;
  int mid_y = display_rect.CenterPoint().y();
  // The top of the mirror rect must be equidistant with the bottom of the
  // original rect from the mid-line.
  result.set_y(mid_y + (mid_y - rect.bottom()));

  // Now make a union with the original rect to ensure we are encompassing both.
  result.Union(rect);
  return result;
}

void RenderText::OnTextAttributeChanged() {
  layout_text_.clear();
  display_text_.clear();
  text_elided_ = false;
  line_breaks_.SetMax(0);

  if (obscured_) {
    size_t obscured_text_length =
        static_cast<size_t>(UTF16IndexToOffset(text_, 0, text_.length()));
    layout_text_.assign(obscured_text_length, kPasswordReplacementChar);

    if (obscured_reveal_index_ >= 0 &&
        obscured_reveal_index_ < static_cast<int>(text_.length())) {
      // Gets the index range in |text_| to be revealed.
      size_t start = obscured_reveal_index_;
      U16_SET_CP_START(text_.data(), 0, start);
      size_t end = start;
      UChar32 unused_char;
      U16_NEXT(text_.data(), end, text_.length(), unused_char);

      // Gets the index in |layout_text_| to be replaced.
      const size_t cp_start =
          static_cast<size_t>(UTF16IndexToOffset(text_, 0, start));
      if (layout_text_.length() > cp_start)
        layout_text_.replace(cp_start, 1, text_.substr(start, end - start));
    }
  } else {
    layout_text_ = text_;
  }

  const base::string16& text = layout_text_;
  if (truncate_length_ > 0 && truncate_length_ < text.length()) {
    // Truncate the text at a valid character break and append an ellipsis.
    icu::StringCharacterIterator iter(text.c_str());
    // Respect ELIDE_HEAD and ELIDE_MIDDLE preferences during truncation.
    if (elide_behavior_ == ELIDE_HEAD) {
      iter.setIndex32(
          static_cast<int32_t>(text.length() - truncate_length_ + 1));
      layout_text_.assign(kEllipsisUTF16 + text.substr(iter.getIndex()));
    } else if (elide_behavior_ == ELIDE_MIDDLE) {
      iter.setIndex32(static_cast<int32_t>(truncate_length_ / 2));
      const size_t ellipsis_start = iter.getIndex();
      iter.setIndex32(
          static_cast<int32_t>(text.length() - (truncate_length_ / 2)));
      const size_t ellipsis_end = iter.getIndex();
      DCHECK_LE(ellipsis_start, ellipsis_end);
      layout_text_.assign(text.substr(0, ellipsis_start) + kEllipsisUTF16 +
                          text.substr(ellipsis_end));
    } else {
      iter.setIndex32(static_cast<int32_t>(truncate_length_ - 1));
      layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16);
    }
  }
  static const base::char16 kNewline[] = { '\n', 0 };
  static const base::char16 kNewlineSymbol[] = { 0x2424, 0 };
  if (!multiline_ && replace_newline_chars_with_symbols_)
    base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_);

  OnLayoutTextAttributeChanged(true);
}

base::string16 RenderText::Elide(const base::string16& text,
                                 float text_width,
                                 float available_width,
                                 ElideBehavior behavior) {
  if (available_width <= 0 || text.empty())
    return base::string16();
  if (behavior == ELIDE_EMAIL)
    return ElideEmail(text, available_width);
  if (text_width > 0 && text_width <= available_width)
    return text;

  TRACE_EVENT0("ui", "RenderText::Elide");

  // Create a RenderText copy with attributes that affect the rendering width.
  std::unique_ptr<RenderText> render_text = CreateInstanceOfSameStyle(text);
  render_text->UpdateStyleLengths();
  if (text_width == 0)
    text_width = render_text->GetContentWidthF();
  if (text_width <= available_width)
    return text;

  const base::string16 ellipsis = base::string16(kEllipsisUTF16);
  const bool insert_ellipsis = (behavior != TRUNCATE);
  const bool elide_in_middle = (behavior == ELIDE_MIDDLE);
  const bool elide_at_beginning = (behavior == ELIDE_HEAD);

  if (insert_ellipsis) {
    render_text->SetText(ellipsis);
    const float ellipsis_width = render_text->GetContentWidthF();
    if (ellipsis_width > available_width)
      return base::string16();
  }

  StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning);

  // Use binary(-like) search to compute the elided text.  In particular, do
  // an interpolation search, which is a binary search in which each guess
  // is an attempt to smartly calculate the right point rather than blindly
  // guessing midway between the endpoints.
  size_t lo = 0;
  size_t hi = text.length() - 1;
  size_t guess = std::string::npos;
  // These two widths are not exactly right but they're good enough to provide
  // some guidance to the search.  For example, |text_width| is actually the
  // length of text.length(), not text.length()-1.
  float lo_width = 0;
  float hi_width = text_width;
  const base::i18n::TextDirection text_direction = GetTextDirection(text);
  while (lo <= hi) {
    // Linearly interpolate between |lo| and |hi|, which correspond to widths
    // of |lo_width| and |hi_width| to estimate at what position
    // |available_width| would be at.  Because |lo_width| and |hi_width| are
    // both estimates (may be off by a little because, for example, |lo_width|
    // may have been calculated from |lo| minus one, not |lo|), we clamp to the
    // the valid range.
    // |last_guess| is merely used to verify that we're not repeating guesses.
    const size_t last_guess = guess;
    guess = lo + static_cast<size_t>(ToRoundedInt((available_width - lo_width) *
                                                  (hi - lo) /
                                                  (hi_width - lo_width)));
    guess = base::ClampToRange(guess, lo, hi);
    DCHECK_NE(last_guess, guess);

    // Restore colors. They will be truncated to size by SetText.
    render_text->colors_ = colors_;
    base::string16 new_text =
        slicer.CutString(guess, insert_ellipsis && behavior != ELIDE_TAIL);

    // This has to be an additional step so that the ellipsis is rendered with
    // same style as trailing part of the text.
    if (insert_ellipsis && behavior == ELIDE_TAIL) {
      // When ellipsis follows text whose directionality is not the same as that
      // of the whole text, it will be rendered with the directionality of the
      // whole text. Since we want ellipsis to indicate continuation of the
      // preceding text, we force the directionality of ellipsis to be same as
      // the preceding text using LTR or RTL markers.
      base::i18n::TextDirection trailing_text_direction =
          base::i18n::GetLastStrongCharacterDirection(new_text);

      // Ensures that the |new_text| will always be smaller or equal to the
      // original text. There is a corner case when only one character is elided
      // and two characters are added back (ellipsis and directional marker).
      if (trailing_text_direction != text_direction &&
          new_text.length() + 2 > text.length() && guess >= 1) {
        new_text = slicer.CutString(guess - 1, false);
      }

      // Append the ellipsis and the optional directional marker characters.
      new_text.append(ellipsis);
      if (trailing_text_direction != text_direction) {
        if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT)
          new_text += base::i18n::kLeftToRightMark;
        else
          new_text += base::i18n::kRightToLeftMark;
      }
    }

    // The elided text must be smaller in bytes. Otherwise, break-lists are not
    // consistent and the characters after the last range are not styled.
    DCHECK_LE(new_text.size(), text.size());
    render_text->SetText(new_text);

    // Restore styles and baselines without breaking multi-character graphemes.
    render_text->styles_ = styles_;
    for (size_t style = 0; style < TEXT_STYLE_COUNT; ++style)
      RestoreBreakList(render_text.get(), &render_text->styles_[style]);
    RestoreBreakList(render_text.get(), &render_text->baselines_);
    RestoreBreakList(render_text.get(), &render_text->font_size_overrides_);
    render_text->weights_ = weights_;
    RestoreBreakList(render_text.get(), &render_text->weights_);

    // We check the width of the whole desired string at once to ensure we
    // handle kerning/ligatures/etc. correctly.
    const float guess_width = render_text->GetContentWidthF();
    if (guess_width == available_width)
      break;
    if (guess_width > available_width) {
      hi = guess - 1;
      hi_width = guess_width;
      // Move back on the loop terminating condition when the guess is too wide.
      if (hi < lo) {
        lo = hi;
        lo_width = guess_width;
      }
    } else {
      lo = guess + 1;
      lo_width = guess_width;
    }
  }

  return render_text->text();
}

base::string16 RenderText::ElideEmail(const base::string16& email,
                                      float available_width) {
  // The returned string will have at least one character besides the ellipsis
  // on either side of '@'; if that's impossible, a single ellipsis is returned.
  // If possible, only the username is elided. Otherwise, the domain is elided
  // in the middle, splitting available width equally with the elided username.
  // If the username is short enough that it doesn't need half the available
  // width, the elided domain will occupy that extra width.

  // Split the email into its local-part (username) and domain-part. The email
  // spec allows for @ symbols in the username under some special requirements,
  // but not in the domain part, so splitting at the last @ symbol is safe.
  const size_t split_index = email.find_last_of('@');
  DCHECK_NE(split_index, base::string16::npos);
  base::string16 username = email.substr(0, split_index);
  base::string16 domain = email.substr(split_index + 1);
  DCHECK(!username.empty());
  DCHECK(!domain.empty());

  // Subtract the @ symbol from the available width as it is mandatory.
  const base::string16 kAtSignUTF16 = base::ASCIIToUTF16("@");
  available_width -= GetStringWidthF(kAtSignUTF16, font_list());

  // Check whether eliding the domain is necessary: if eliding the username
  // is sufficient, the domain will not be elided.
  const float full_username_width = GetStringWidthF(username, font_list());
  const float available_domain_width = available_width -
      std::min(full_username_width,
          GetStringWidthF(username.substr(0, 1) + kEllipsisUTF16, font_list()));
  if (GetStringWidthF(domain, font_list()) > available_domain_width) {
    // Elide the domain so that it only takes half of the available width.
    // Should the username not need all the width available in its half, the
    // domain will occupy the leftover width.
    // If |desired_domain_width| is greater than |available_domain_width|: the
    // minimal username elision allowed by the specifications will not fit; thus
    // |desired_domain_width| must be <= |available_domain_width| at all cost.
    const float desired_domain_width =
        std::min<float>(available_domain_width,
            std::max<float>(available_width - full_username_width,
                            available_width / 2));
    domain = Elide(domain, 0, desired_domain_width, ELIDE_MIDDLE);
    // Failing to elide the domain such that at least one character remains
    // (other than the ellipsis itself) remains: return a single ellipsis.
    if (domain.length() <= 1U)
      return base::string16(kEllipsisUTF16);
  }

  // Fit the username in the remaining width (at this point the elided username
  // is guaranteed to fit with at least one character remaining given all the
  // precautions taken earlier).
  available_width -= GetStringWidthF(domain, font_list());
  username = Elide(username, 0, available_width, ELIDE_TAIL);
  return username + kAtSignUTF16 + domain;
}

void RenderText::UpdateCachedBoundsAndOffset() {
  if (cached_bounds_and_offset_valid_)
    return;

  // TODO(ckocagil): Add support for scrolling multiline text.

  int delta_x = 0;

  if (cursor_enabled()) {
    // When cursor is enabled, ensure it is visible. For this, set the valid
    // flag true and calculate the current cursor bounds using the stale
    // |display_offset_|. Then calculate the change in offset needed to move the
    // cursor into the visible area.
    cached_bounds_and_offset_valid_ = true;
    cursor_bounds_ = GetCursorBounds(selection_model_, true);

    // TODO(bidi): Show RTL glyphs at the cursor position for ALIGN_LEFT, etc.
    if (cursor_bounds_.right() > display_rect_.right())
      delta_x = display_rect_.right() - cursor_bounds_.right();
    else if (cursor_bounds_.x() < display_rect_.x())
      delta_x = display_rect_.x() - cursor_bounds_.x();
  }

  SetDisplayOffset(display_offset_.x() + delta_x);
}

void RenderText::DrawSelection(Canvas* canvas) {
  for (Rect s : GetSubstringBounds(selection())) {
    if (symmetric_selection_visual_bounds() && !multiline())
      s = ExpandToBeVerticallySymmetric(s, display_rect());
    canvas->FillRect(s, selection_background_focused_color_);
  }
}

size_t RenderText::GetNearestWordStartBoundary(size_t index) const {
  const size_t length = text().length();
  if (obscured() || length == 0)
    return length;

  base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
  const bool success = iter.Init();
  DCHECK(success);
  if (!success)
    return length;

  // First search for the word start boundary in the CURSOR_BACKWARD direction,
  // then in the CURSOR_FORWARD direction.
  for (int i = static_cast<int>(std::min(index, length - 1)); i >= 0; i--)
    if (iter.IsStartOfWord(i))
      return i;

  for (size_t i = index + 1; i < length; i++)
    if (iter.IsStartOfWord(i))
      return i;

  return length;
}

Range RenderText::ExpandRangeToWordBoundary(const Range& range) const {
  const size_t length = text().length();
  DCHECK_LE(range.GetMax(), length);
  if (obscured())
    return range.is_reversed() ? Range(length, 0) : Range(0, length);

  base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
  const bool success = iter.Init();
  DCHECK(success);
  if (!success)
    return range;

  size_t range_min = range.GetMin();
  if (range_min == length && range_min != 0)
    --range_min;

  for (; range_min != 0; --range_min)
    if (iter.IsStartOfWord(range_min) || iter.IsEndOfWord(range_min))
      break;

  size_t range_max = range.GetMax();
  if (range_min == range_max && range_max != length)
    ++range_max;

  for (; range_max < length; ++range_max)
    if (iter.IsEndOfWord(range_max) || iter.IsStartOfWord(range_max))
      break;

  return range.is_reversed() ? Range(range_max, range_min)
                             : Range(range_min, range_max);
}

internal::TextRunList* RenderText::GetRunList() {
  NOTREACHED();
  return nullptr;
}

const internal::TextRunList* RenderText::GetRunList() const {
  NOTREACHED();
  return nullptr;
}

void RenderText::SetGlyphWidthForTest(float test_width) {
  NOTREACHED();
}

}  // namespace gfx
