Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2666)

Unified Diff: app/text_elider.cc

Issue 5964007: Last part of change for bug 49747.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « app/text_elider.h ('k') | app/text_elider_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: app/text_elider.cc
===================================================================
--- app/text_elider.cc (revision 69878)
+++ app/text_elider.cc (working copy)
@@ -6,6 +6,8 @@
#include "app/text_elider.h"
#include "base/file_path.h"
+#include "base/i18n/break_iterator.h"
+#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
#include "base/string_split.h"
#include "base/string_util.h"
@@ -498,3 +500,168 @@
}
} // namespace gfx
+
+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, string16 *output)
+ : max_rows_(max_rows),
+ max_cols_(max_cols),
+ current_row_(0),
+ current_col_(0),
+ suppressed_(false),
+ output_(output) {}
+
+ // Perform deferred initializions 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 string16& input);
+
+ // Perform any deferred output processing. Must be called after the
+ // last AddString() call has occured.
+ 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 string16& line);
+
+ // Add a word to the rectangluar region at the current position,
+ // either by itelf or by breaking it into characters.
+ void AddWord(const string16& word);
+
+ // Add text to the output string if the rectangular boundaries
+ // have not been exceeded, advancing the current position.
+ void Append(const string16& string);
+
+ // Add a newline to the output string if the rectangular boundaries
+ // have not been exceeded, resetting the current position to the
+ // beginning of the next line.
+ void NewLine();
+
+ // 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 some of the input has been truncated.
+ bool suppressed_;
+
+ // String onto which the output is accumulated.
+ string16 *output_;
+};
+
+void RectangleString::AddString(const string16& input) {
+ base::BreakIterator lines(&input, base::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 string16& line) {
+ if (line.length() < max_cols_) {
+ Append(line);
+ } else {
+ base::BreakIterator words(&line, base::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 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();
+ Append(word);
+ } else {
+ // Word is so big that it must be fragmented.
+ int array_start = 0;
+ int char_start = 0;
+ base::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();
+ array_start = chars.array_pos();
+ char_start = chars.char_pos();
+ }
+ chars.Advance();
+ }
+ // add 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 string16& string) {
+ if (current_row_ < max_rows_)
+ output_->append(string);
+ else
+ suppressed_ = true;
+ current_col_ += string.length();
+}
+
+void RectangleString::NewLine() {
+ if (current_row_ < max_rows_)
+ output_->append(ASCIIToUTF16("\n"));
+ else
+ suppressed_ = true;
+ ++current_row_;
+ current_col_ = 0;
+}
+
+} // namespace
+
+namespace gfx {
+
+bool ElideRectangleString(const string16& input, size_t max_rows,
+ size_t max_cols, string16* output) {
+ RectangleString rect(max_rows, max_cols, output);
+ rect.Init();
+ rect.AddString(input);
+ return rect.Finalize();
+}
+
+} // namespace gfx
+
« no previous file with comments | « app/text_elider.h ('k') | app/text_elider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698