Index: ui/base/text/text_elider.cc |
diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc |
index 1a4b79d5e2e9ebbcbeeffdc6e35e79bff4b2b9cb..8cbfb3c3c8821179983c3b07a2a669999528558a 100644 |
--- a/ui/base/text/text_elider.cc |
+++ b/ui/base/text/text_elider.cc |
@@ -10,6 +10,7 @@ |
#include "base/i18n/break_iterator.h" |
#include "base/i18n/char_iterator.h" |
#include "base/i18n/rtl.h" |
+#include "base/scoped_ptr.h" |
#include "base/string_split.h" |
#include "base/string_util.h" |
#include "base/sys_string_conversions.h" |
@@ -19,6 +20,8 @@ |
#include "net/base/net_util.h" |
#include "net/base/registry_controlled_domain.h" |
#include "ui/gfx/font.h" |
+#include "unicode/rbbi.h" |
+#include "unicode/uloc.h" |
namespace ui { |
@@ -673,4 +676,67 @@ bool ElideRectangleString(const string16& input, size_t max_rows, |
return rect.Finalize(); |
} |
+string16 TruncateString(const string16& string, size_t length) { |
+ if (string.size() <= length) |
+ // String fits, return it. |
+ return string; |
+ |
+ if (length == 0) { |
+ // No room for the elide string, return an empty string. |
+ return string16(); |
+ } |
+ size_t max = length - 1; |
+ |
+ // Added to the end of strings that are too big. |
+ static const char16 kElideString[] = { 0x2026, 0 }; |
+ |
+ if (max == 0) { |
+ // Just enough room for the elide string. |
+ return kElideString; |
+ } |
+ |
+ // Use a line iterator to find the first boundary. |
+ UErrorCode status = U_ZERO_ERROR; |
+ scoped_ptr<icu::RuleBasedBreakIterator> bi( |
+ static_cast<icu::RuleBasedBreakIterator*>( |
+ icu::RuleBasedBreakIterator::createLineInstance( |
+ icu::Locale::getDefault(), status))); |
+ if (U_FAILURE(status)) |
+ return string.substr(0, max) + kElideString; |
+ bi->setText(string.c_str()); |
+ int32_t index = bi->preceding(static_cast<int32_t>(max)); |
+ if (index == icu::BreakIterator::DONE) { |
+ index = static_cast<int32_t>(max); |
+ } else { |
+ // Found a valid break (may be the beginning of the string). Now use |
+ // a character iterator to find the previous non-whitespace character. |
+ icu::StringCharacterIterator char_iterator(string.c_str()); |
+ if (index == 0) { |
+ // No valid line breaks. Start at the end again. This ensures we break |
+ // on a valid character boundary. |
+ index = static_cast<int32_t>(max); |
+ } |
+ 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 ui |