// 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.
//
// This file implements utility functions for eliding and formatting UI text.
//
// Note that several of the functions declared in text_elider.h are implemented
// in this file using helper classes in an unnamed namespace.

#include "ui/gfx/text_elider.h"

#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/i18n/break_iterator.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/icu/source/common/unicode/rbbi.h"
#include "third_party/icu/source/common/unicode/uloc.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_utils.h"

using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
using base::WideToUTF16;

namespace gfx {

namespace {

#if defined(OS_ANDROID) || defined(OS_IOS)
// 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.
base::string16 ElideEmail(const base::string16& email,
                          const FontList& font_list,
                          float available_pixel_width) {
  if (GetStringWidthF(email, font_list) <= available_pixel_width)
    return email;

  // 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 = ASCIIToUTF16("@");
  available_pixel_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_pixel_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(available_domain_width,
                 std::max(available_pixel_width - full_username_width,
                          available_pixel_width / 2));
    domain = ElideText(domain, font_list, 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_pixel_width -= GetStringWidthF(domain, font_list);
  username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL);
  return username + kAtSignUTF16 + domain;
}
#endif

}  // namespace

// U+2026 in utf8
const char kEllipsis[] = "\xE2\x80\xA6";
const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
const base::char16 kForwardSlash = '/';

StringSlicer::StringSlicer(const base::string16& text,
                           const base::string16& ellipsis,
                           bool elide_in_middle,
                           bool elide_at_beginning)
    : text_(text),
      ellipsis_(ellipsis),
      elide_in_middle_(elide_in_middle),
      elide_at_beginning_(elide_at_beginning) {
}

base::string16 StringSlicer::CutString(size_t length, bool insert_ellipsis) {
  const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
                                                       : base::string16();

  if (elide_at_beginning_)
    return ellipsis_text +
           text_.substr(FindValidBoundaryBefore(text_.length() - length));

  if (!elide_in_middle_)
    return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text;

  // We put the extra character, if any, before the cut.
  const size_t half_length = length / 2;
  const size_t prefix_length = FindValidBoundaryBefore(length - half_length);
  const size_t suffix_start_guess = text_.length() - half_length;
  const size_t suffix_start = FindValidBoundaryAfter(suffix_start_guess);
  const size_t suffix_length =
      half_length - (suffix_start_guess - suffix_start);
  return text_.substr(0, prefix_length) + ellipsis_text +
         text_.substr(suffix_start, suffix_length);
}

size_t StringSlicer::FindValidBoundaryBefore(size_t index) const {
  DCHECK_LE(index, text_.length());
  if (index != text_.length())
    U16_SET_CP_START(text_.data(), 0, index);
  return index;
}

size_t StringSlicer::FindValidBoundaryAfter(size_t index) const {
  DCHECK_LE(index, text_.length());
  if (index == text_.length())
    return index;

  int32_t text_index = base::checked_cast<int32_t>(index);
  int32_t text_length = base::checked_cast<int32_t>(text_.length());
  U16_SET_CP_LIMIT(text_.data(), 0, text_index, text_length);
  return static_cast<size_t>(text_index);
}

base::string16 ElideFilename(const base::FilePath& filename,
                             const FontList& font_list,
                             float available_pixel_width) {
#if defined(OS_WIN)
  base::string16 filename_utf16 = filename.value();
  base::string16 extension = filename.Extension();
  base::string16 rootname = filename.BaseName().RemoveExtension().value();
#elif defined(OS_POSIX)
  base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide(
      filename.value()));
  base::string16 extension = WideToUTF16(base::SysNativeMBToWide(
      filename.Extension()));
  base::string16 rootname = WideToUTF16(base::SysNativeMBToWide(
      filename.BaseName().RemoveExtension().value()));
#endif

  const float full_width = GetStringWidthF(filename_utf16, font_list);
  if (full_width <= available_pixel_width)
    return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16);

  if (rootname.empty() || extension.empty()) {
    const base::string16 elided_name =
        ElideText(filename_utf16, font_list, available_pixel_width, ELIDE_TAIL);
    return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
  }

  const float ext_width = GetStringWidthF(extension, font_list);
  const float root_width = GetStringWidthF(rootname, font_list);

  // We may have trimmed the path.
  if (root_width + ext_width <= available_pixel_width) {
    const base::string16 elided_name = rootname + extension;
    return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
  }

  if (ext_width >= available_pixel_width) {
    const base::string16 elided_name = ElideText(
        rootname + extension, font_list, available_pixel_width, ELIDE_MIDDLE);
    return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
  }

  float available_root_width = available_pixel_width - ext_width;
  base::string16 elided_name =
      ElideText(rootname, font_list, available_root_width, ELIDE_TAIL);
  elided_name += extension;
  return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}

base::string16 ElideText(const base::string16& text,
                         const FontList& font_list,
                         float available_pixel_width,
                         ElideBehavior behavior) {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
  DCHECK_NE(behavior, FADE_TAIL);
  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
  render_text->SetCursorEnabled(false);
  // Do not bother accurately sizing strings over 5000 characters here, for
  // performance purposes. This matches the behavior of Canvas::SizeStringFloat.
  render_text->set_truncate_length(5000);
  render_text->SetFontList(font_list);
  available_pixel_width = std::ceil(available_pixel_width);
  render_text->SetDisplayRect(gfx::Rect(gfx::Size(available_pixel_width, 1)));
  render_text->SetElideBehavior(behavior);
  render_text->SetText(text);
  return render_text->layout_text();
#else
  DCHECK_NE(behavior, FADE_TAIL);
  if (text.empty() || behavior == FADE_TAIL || behavior == NO_ELIDE ||
      GetStringWidthF(text, font_list) <= available_pixel_width) {
    return text;
  }
  if (behavior == ELIDE_EMAIL)
    return ElideEmail(text, font_list, available_pixel_width);

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

  if (insert_ellipsis &&
      GetStringWidthF(ellipsis, font_list) > available_pixel_width)
    return base::string16();

  // Use binary search to compute the elided text.
  size_t lo = 0;
  size_t hi = text.length() - 1;
  size_t guess;
  for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
    // We check the width of the whole desired string at once to ensure we
    // handle kerning/ligatures/etc. correctly.
    // TODO(skanuj) : Handle directionality of ellipsis based on adjacent
    // characters.  See crbug.com/327963.
    const base::string16 cut = slicer.CutString(guess, insert_ellipsis);
    const float guess_width = GetStringWidthF(cut, font_list);
    if (guess_width == available_pixel_width)
      break;
    if (guess_width > available_pixel_width) {
      hi = guess - 1;
      // Move back on the loop terminating condition when the guess is too wide.
      if (hi < lo)
        lo = hi;
    } else {
      lo = guess + 1;
    }
  }

  return slicer.CutString(guess, insert_ellipsis);
#endif
}

bool ElideString(const base::string16& input,
                 int max_len,
                 base::string16* output) {
  DCHECK_GE(max_len, 0);
  if (static_cast<int>(input.length()) <= max_len) {
    output->assign(input);
    return false;
  }

  switch (max_len) {
    case 0:
      output->clear();
      break;
    case 1:
      output->assign(input.substr(0, 1));
      break;
    case 2:
      output->assign(input.substr(0, 2));
      break;
    case 3:
      output->assign(input.substr(0, 1) + ASCIIToUTF16(".") +
                     input.substr(input.length() - 1));
      break;
    case 4:
      output->assign(input.substr(0, 1) + ASCIIToUTF16("..") +
                     input.substr(input.length() - 1));
      break;
    default: {
      int rstr_len = (max_len - 3) / 2;
      int lstr_len = rstr_len + ((max_len - 3) % 2);
      output->assign(input.substr(0, lstr_len) + ASCIIToUTF16("...") +
                     input.substr(input.length() - rstr_len));
      break;
    }
  }

  return true;
}

namespace {

// Internal class used to track progress of a rectangular string elide
// operation.  Exists so the top-level ElideRectangleString() function
// can be broken into smaller methods sharing this state.
class RectangleString {
 public:
  RectangleString(size_t max_rows, size_t max_cols,
                  bool strict, base::string16 *output)
      : max_rows_(max_rows),
        max_cols_(max_cols),
        current_row_(0),
        current_col_(0),
        strict_(strict),
        suppressed_(false),
        output_(output) {}

  // Perform deferred initializations following creation.  Must be called
  // before any input can be added via AddString().
  void Init() { output_->clear(); }

  // Add an input string, reformatting to fit the desired dimensions.
  // AddString() may be called multiple times to concatenate together
  // multiple strings into the region (the current caller doesn't do
  // this, however).
  void AddString(const base::string16& input);

  // Perform any deferred output processing.  Must be called after the
  // last AddString() call has occurred.
  bool Finalize();

 private:
  // Add a line to the rectangular region at the current position,
  // either by itself or by breaking it into words.
  void AddLine(const base::string16& line);

  // Add a word to the rectangular region at the current position,
  // either by itself or by breaking it into characters.
  void AddWord(const base::string16& word);

  // Add text to the output string if the rectangular boundaries
  // have not been exceeded, advancing the current position.
  void Append(const base::string16& string);

  // Set the current position to the beginning of the next line.  If
  // |output| is true, add a newline to the output string if the rectangular
  // boundaries have not been exceeded.  If |output| is false, we assume
  // some other mechanism will (likely) do similar breaking after the fact.
  void NewLine(bool output);

  // Maximum number of rows allowed in the output string.
  size_t max_rows_;

  // Maximum number of characters allowed in the output string.
  size_t max_cols_;

  // Current row position, always incremented and may exceed max_rows_
  // when the input can not fit in the region.  We stop appending to
  // the output string, however, when this condition occurs.  In the
  // future, we may want to expose this value to allow the caller to
  // determine how many rows would actually be required to hold the
  // formatted string.
  size_t current_row_;

  // Current character position, should never exceed max_cols_.
  size_t current_col_;

  // True when we do whitespace to newline conversions ourselves.
  bool strict_;

  // True when some of the input has been truncated.
  bool suppressed_;

  // String onto which the output is accumulated.
  base::string16* output_;

  DISALLOW_COPY_AND_ASSIGN(RectangleString);
};

void RectangleString::AddString(const base::string16& input) {
  base::i18n::BreakIterator lines(input,
                                  base::i18n::BreakIterator::BREAK_NEWLINE);
  if (lines.Init()) {
    while (lines.Advance())
      AddLine(lines.GetString());
  } else {
    NOTREACHED() << "BreakIterator (lines) init failed";
  }
}

bool RectangleString::Finalize() {
  if (suppressed_) {
    output_->append(ASCIIToUTF16("..."));
    return true;
  }
  return false;
}

void RectangleString::AddLine(const base::string16& line) {
  if (line.length() < max_cols_) {
    Append(line);
  } else {
    base::i18n::BreakIterator words(line,
                                    base::i18n::BreakIterator::BREAK_SPACE);
    if (words.Init()) {
      while (words.Advance())
        AddWord(words.GetString());
    } else {
      NOTREACHED() << "BreakIterator (words) init failed";
    }
  }
  // Account for naturally-occuring newlines.
  ++current_row_;
  current_col_ = 0;
}

void RectangleString::AddWord(const base::string16& word) {
  if (word.length() < max_cols_) {
    // Word can be made to fit, no need to fragment it.
    if (current_col_ + word.length() >= max_cols_)
      NewLine(strict_);
    Append(word);
  } else {
    // Word is so big that it must be fragmented.
    int array_start = 0;
    int char_start = 0;
    base::i18n::UTF16CharIterator chars(&word);
    while (!chars.end()) {
      // When boundary is hit, add as much as will fit on this line.
      if (current_col_ + (chars.char_pos() - char_start) >= max_cols_) {
        Append(word.substr(array_start, chars.array_pos() - array_start));
        NewLine(true);
        array_start = chars.array_pos();
        char_start = chars.char_pos();
      }
      chars.Advance();
    }
    // Add the last remaining fragment, if any.
    if (array_start != chars.array_pos())
      Append(word.substr(array_start, chars.array_pos() - array_start));
  }
}

void RectangleString::Append(const base::string16& string) {
  if (current_row_ < max_rows_)
    output_->append(string);
  else
    suppressed_ = true;
  current_col_ += string.length();
}

void RectangleString::NewLine(bool output) {
  if (current_row_ < max_rows_) {
    if (output)
      output_->append(ASCIIToUTF16("\n"));
  } else {
    suppressed_ = true;
  }
  ++current_row_;
  current_col_ = 0;
}

// Internal class used to track progress of a rectangular text elide
// operation.  Exists so the top-level ElideRectangleText() function
// can be broken into smaller methods sharing this state.
class RectangleText {
 public:
  RectangleText(const FontList& font_list,
                float available_pixel_width,
                int available_pixel_height,
                WordWrapBehavior wrap_behavior,
                std::vector<base::string16>* lines)
      : font_list_(font_list),
        line_height_(font_list.GetHeight()),
        available_pixel_width_(available_pixel_width),
        available_pixel_height_(available_pixel_height),
        wrap_behavior_(wrap_behavior),
        current_width_(0),
        current_height_(0),
        last_line_ended_in_lf_(false),
        lines_(lines),
        insufficient_width_(false),
        insufficient_height_(false) {}

  // Perform deferred initializions following creation.  Must be called
  // before any input can be added via AddString().
  void Init() { lines_->clear(); }

  // Add an input string, reformatting to fit the desired dimensions.
  // AddString() may be called multiple times to concatenate together
  // multiple strings into the region (the current caller doesn't do
  // this, however).
  void AddString(const base::string16& input);

  // Perform any deferred output processing.  Must be called after the last
  // AddString() call has occured. Returns a combination of
  // |ReformattingResultFlags| indicating whether the given width or height was
  // insufficient, leading to elision or truncation.
  int Finalize();

 private:
  // Add a line to the rectangular region at the current position,
  // either by itself or by breaking it into words.
  void AddLine(const base::string16& line);

  // Wrap the specified word across multiple lines.
  int WrapWord(const base::string16& word);

  // Add a long word - wrapping, eliding or truncating per the wrap behavior.
  int AddWordOverflow(const base::string16& word);

  // Add a word to the rectangluar region at the current position.
  int AddWord(const base::string16& word);

  // Append the specified |text| to the current output line, incrementing the
  // running width by the specified amount. This is an optimization over
  // |AddToCurrentLine()| when |text_width| is already known.
  void AddToCurrentLineWithWidth(const base::string16& text, float text_width);

  // Append the specified |text| to the current output line.
  void AddToCurrentLine(const base::string16& text);

  // Set the current position to the beginning of the next line.
  bool NewLine();

  // The font list used for measuring text width.
  const FontList& font_list_;

  // The height of each line of text.
  const int line_height_;

  // The number of pixels of available width in the rectangle.
  const float available_pixel_width_;

  // The number of pixels of available height in the rectangle.
  const int available_pixel_height_;

  // The wrap behavior for words that are too long to fit on a single line.
  const WordWrapBehavior wrap_behavior_;

  // The current running width.
  float current_width_;

  // The current running height.
  int current_height_;

  // The current line of text.
  base::string16 current_line_;

  // Indicates whether the last line ended with \n.
  bool last_line_ended_in_lf_;

  // The output vector of lines.
  std::vector<base::string16>* lines_;

  // Indicates whether a word was so long that it had to be truncated or elided
  // to fit the available width.
  bool insufficient_width_;

  // Indicates whether there were too many lines for the available height.
  bool insufficient_height_;

  DISALLOW_COPY_AND_ASSIGN(RectangleText);
};

void RectangleText::AddString(const base::string16& input) {
  base::i18n::BreakIterator lines(input,
                                  base::i18n::BreakIterator::BREAK_NEWLINE);
  if (lines.Init()) {
    while (!insufficient_height_ && lines.Advance()) {
      base::string16 line = lines.GetString();
      // The BREAK_NEWLINE iterator will keep the trailing newline character,
      // except in the case of the last line, which may not have one.  Remove
      // the newline character, if it exists.
      last_line_ended_in_lf_ = !line.empty() && line[line.length() - 1] == '\n';
      if (last_line_ended_in_lf_)
        line.resize(line.length() - 1);
      AddLine(line);
    }
  } else {
    NOTREACHED() << "BreakIterator (lines) init failed";
  }
}

int RectangleText::Finalize() {
  // Remove trailing whitespace from the last line or remove the last line
  // completely, if it's just whitespace.
  if (!insufficient_height_ && !lines_->empty()) {
    base::TrimWhitespace(lines_->back(), base::TRIM_TRAILING, &lines_->back());
    if (lines_->back().empty() && !last_line_ended_in_lf_)
      lines_->pop_back();
  }
  if (last_line_ended_in_lf_)
    lines_->push_back(base::string16());
  return (insufficient_width_ ? INSUFFICIENT_SPACE_HORIZONTAL : 0) |
         (insufficient_height_ ? INSUFFICIENT_SPACE_VERTICAL : 0);
}

void RectangleText::AddLine(const base::string16& line) {
  const float line_width = GetStringWidthF(line, font_list_);
  if (line_width <= available_pixel_width_) {
    AddToCurrentLineWithWidth(line, line_width);
  } else {
    // Iterate over positions that are valid to break the line at. In general,
    // these are word boundaries but after any punctuation following the word.
    base::i18n::BreakIterator words(line,
                                    base::i18n::BreakIterator::BREAK_LINE);
    if (words.Init()) {
      while (words.Advance()) {
        const bool truncate = !current_line_.empty();
        const base::string16& word = words.GetString();
        const int lines_added = AddWord(word);
        if (lines_added) {
          if (truncate) {
            // Trim trailing whitespace from the line that was added.
            const int line = lines_->size() - lines_added;
            base::TrimWhitespace(lines_->at(line), base::TRIM_TRAILING,
                                 &lines_->at(line));
          }
          if (base::ContainsOnlyChars(word, base::kWhitespaceUTF16)) {
            // Skip the first space if the previous line was carried over.
            current_width_ = 0;
            current_line_.clear();
          }
        }
      }
    } else {
      NOTREACHED() << "BreakIterator (words) init failed";
    }
  }
  // Account for naturally-occuring newlines.
  NewLine();
}

int RectangleText::WrapWord(const base::string16& word) {
  // Word is so wide that it must be fragmented.
  base::string16 text = word;
  int lines_added = 0;
  bool first_fragment = true;
  while (!insufficient_height_ && !text.empty()) {
    base::string16 fragment =
        ElideText(text, font_list_, available_pixel_width_, TRUNCATE);
    // At least one character has to be added at every line, even if the
    // available space is too small.
    if (fragment.empty())
      fragment = text.substr(0, 1);
    if (!first_fragment && NewLine())
      lines_added++;
    AddToCurrentLine(fragment);
    text = text.substr(fragment.length());
    first_fragment = false;
  }
  return lines_added;
}

int RectangleText::AddWordOverflow(const base::string16& word) {
  int lines_added = 0;

  // Unless this is the very first word, put it on a new line.
  if (!current_line_.empty()) {
    if (!NewLine())
      return 0;
    lines_added++;
  }

  if (wrap_behavior_ == IGNORE_LONG_WORDS) {
    current_line_ = word;
    current_width_ = available_pixel_width_;
  } else if (wrap_behavior_ == WRAP_LONG_WORDS) {
    lines_added += WrapWord(word);
  } else {
    const ElideBehavior elide_behavior =
        (wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_TAIL : TRUNCATE);
    const base::string16 elided_word =
        ElideText(word, font_list_, available_pixel_width_, elide_behavior);
    AddToCurrentLine(elided_word);
    insufficient_width_ = true;
  }

  return lines_added;
}

int RectangleText::AddWord(const base::string16& word) {
  int lines_added = 0;
  base::string16 trimmed;
  base::TrimWhitespace(word, base::TRIM_TRAILING, &trimmed);
  const float trimmed_width = GetStringWidthF(trimmed, font_list_);
  if (trimmed_width <= available_pixel_width_) {
    // Word can be made to fit, no need to fragment it.
    if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine())
      lines_added++;
    // Append the non-trimmed word, in case more words are added after.
    AddToCurrentLine(word);
  } else {
    lines_added = AddWordOverflow(wrap_behavior_ == IGNORE_LONG_WORDS ?
                                  trimmed : word);
  }
  return lines_added;
}

void RectangleText::AddToCurrentLine(const base::string16& text) {
  AddToCurrentLineWithWidth(text, GetStringWidthF(text, font_list_));
}

void RectangleText::AddToCurrentLineWithWidth(const base::string16& text,
                                              float text_width) {
  if (current_height_ >= available_pixel_height_) {
    insufficient_height_ = true;
    return;
  }
  current_line_.append(text);
  current_width_ += text_width;
}

bool RectangleText::NewLine() {
  bool line_added = false;
  if (current_height_ < available_pixel_height_) {
    lines_->push_back(current_line_);
    current_line_.clear();
    line_added = true;
  } else {
    insufficient_height_ = true;
  }
  current_height_ += line_height_;
  current_width_ = 0;
  return line_added;
}

}  // namespace

bool ElideRectangleString(const base::string16& input, size_t max_rows,
                          size_t max_cols, bool strict,
                          base::string16* output) {
  RectangleString rect(max_rows, max_cols, strict, output);
  rect.Init();
  rect.AddString(input);
  return rect.Finalize();
}

int ElideRectangleText(const base::string16& input,
                       const FontList& font_list,
                       float available_pixel_width,
                       int available_pixel_height,
                       WordWrapBehavior wrap_behavior,
                       std::vector<base::string16>* lines) {
  RectangleText rect(font_list,
                     available_pixel_width,
                     available_pixel_height,
                     wrap_behavior,
                     lines);
  rect.Init();
  rect.AddString(input);
  return rect.Finalize();
}

base::string16 TruncateString(const base::string16& string,
                              size_t length,
                              BreakType break_type) {
  DCHECK(break_type == CHARACTER_BREAK || break_type == WORD_BREAK);

  if (string.size() <= length)
    // String fits, return it.
    return string;

  if (length == 0)
    // No room for the elide string, return an empty string.
    return base::string16();

  size_t max = length - 1;

  // Added to the end of strings that are too big.
  static const base::char16 kElideString[] = { 0x2026, 0 };

  if (max == 0)
    // Just enough room for the elide string.
    return kElideString;

  int32_t index = static_cast<int32_t>(max);
  if (break_type == WORD_BREAK) {
    // Use a line iterator to find the first boundary.
    UErrorCode status = U_ZERO_ERROR;
    scoped_ptr<icu::BreakIterator> bi(
        icu::RuleBasedBreakIterator::createLineInstance(
            icu::Locale::getDefault(), status));
    if (U_FAILURE(status))
      return string.substr(0, max) + kElideString;
    bi->setText(string.c_str());
    index = bi->preceding(index);
    if (index == icu::BreakIterator::DONE || index == 0) {
      // We either found no valid line break at all, or one right at the
      // beginning of the string. Go back to the end; we'll have to break in the
      // middle of a word.
      index = static_cast<int32_t>(max);
    }
  }

  // Use a character iterator to find the previous non-whitespace character.
  icu::StringCharacterIterator char_iterator(string.c_str());
  char_iterator.setIndex(index);
  while (char_iterator.hasPrevious()) {
    char_iterator.previous();
    if (!(u_isspace(char_iterator.current()) ||
          u_charType(char_iterator.current()) == U_CONTROL_CHAR ||
          u_charType(char_iterator.current()) == U_NON_SPACING_MARK)) {
      // Not a whitespace character. Advance the iterator so that we
      // include the current character in the truncated string.
      char_iterator.next();
      break;
    }
  }
  if (char_iterator.hasPrevious()) {
    // Found a valid break point.
    index = char_iterator.getIndex();
  } else {
    // String has leading whitespace, return the elide string.
    return kElideString;
  }

  return string.substr(0, index) + kElideString;
}

}  // namespace gfx
