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

Unified Diff: ui/gfx/text_elider.cc

Issue 112063003: Implement eliding/truncating at end in RenderText (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Synced Created 7 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 | « ui/gfx/text_elider.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/text_elider.cc
diff --git a/ui/gfx/text_elider.cc b/ui/gfx/text_elider.cc
index 5b9469614f22f8080a5dee020af64a4058264669..c58a96d9748b4c357e29a07ef01a97cd6f1a3ac9 100644
--- a/ui/gfx/text_elider.cc
+++ b/ui/gfx/text_elider.cc
@@ -39,68 +39,6 @@ const base::char16 kForwardSlash = '/';
namespace {
-// Helper class to split + elide text, while respecting UTF16 surrogate pairs.
-class StringSlicer {
- public:
- StringSlicer(const base::string16& text,
- const base::string16& ellipsis,
- bool elide_in_middle)
- : text_(text),
- ellipsis_(ellipsis),
- elide_in_middle_(elide_in_middle) {
- }
-
- // Cuts |text_| to be |length| characters long. If |elide_in_middle_| is true,
- // the middle of the string is removed to leave equal-length pieces from the
- // beginning and end of the string; otherwise, the end of the string is
- // removed and only the beginning remains. If |insert_ellipsis| is true,
- // then an ellipsis character will be inserted at the cut point.
- base::string16 CutString(size_t length, bool insert_ellipsis) {
- const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
- : base::string16();
-
- 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);
- }
-
- private:
- // Returns a valid cut boundary at or before |index|.
- size_t FindValidBoundaryBefore(size_t index) const {
- DCHECK_LE(index, text_.length());
- if (index != text_.length())
- U16_SET_CP_START(text_.data(), 0, index);
- return index;
- }
-
- // Returns a valid cut boundary at or after |index|.
- size_t FindValidBoundaryAfter(size_t index) const {
- DCHECK_LE(index, text_.length());
- if (index != text_.length())
- U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length());
- return index;
- }
-
- // The text to be sliced.
- const base::string16& text_;
-
- // Ellipsis string to use.
- const base::string16& ellipsis_;
-
- // If true, the middle of the string will be elided.
- bool elide_in_middle_;
-
- DISALLOW_COPY_AND_ASSIGN(StringSlicer);
-};
// Build a path from the first |num_components| elements in |path_elements|.
// Prepends |path_prefix|, appends |filename|, inserts ellipsis if appropriate.
@@ -150,6 +88,46 @@ base::string16 ElideComponentizedPath(
} // namespace
+StringSlicer::StringSlicer(const base::string16& text,
+ const base::string16& ellipsis,
+ bool elide_in_middle)
+ : text_(text),
+ ellipsis_(ellipsis),
+ elide_in_middle_(elide_in_middle) {
+}
+
+base::string16 StringSlicer::CutString(size_t length, bool insert_ellipsis) {
+ const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
+ : base::string16();
+
+ 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())
+ U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length());
+ return index;
+}
+
base::string16 ElideEmail(const base::string16& email,
const FontList& font_list,
float available_pixel_width) {
@@ -477,7 +455,8 @@ base::string16 ElideText(const base::string16& text,
// (eliding way too much from a ridiculous string is probably still
// ridiculous), but we should check other widths for bogus values as well.
if (current_text_pixel_width <= 0 && !text.empty()) {
- const base::string16 cut = slicer.CutString(text.length() / 2, false);
+ const base::string16 cut =
+ slicer.CutString(text.length() / 2, insert_ellipsis);
return ElideText(cut, font_list, available_pixel_width, elide_behavior);
}
@@ -493,20 +472,23 @@ base::string16 ElideText(const base::string16& text,
size_t hi = text.length() - 1;
size_t guess;
for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
- // We check the length of the whole desired string at once to ensure we
+ // 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_length = GetStringWidthF(cut, font_list);
- // Check again that we didn't hit a Pango width overflow. If so, cut the
- // current string in half and start over.
- if (guess_length <= 0) {
- return ElideText(slicer.CutString(guess / 2, false),
- font_list, available_pixel_width, elide_behavior);
- }
- if (guess_length > available_pixel_width)
+ const float guess_width = GetStringWidthF(cut, font_list);
+ if (guess_width == available_pixel_width)
+ break;
+ if (guess_width > available_pixel_width) {
hi = guess - 1;
- else
+ // Move back if we are on loop terminating condition, and guess is wider
+ // than available.
+ if (hi < lo)
+ lo = hi;
+ } else {
lo = guess + 1;
+ }
}
return slicer.CutString(guess, insert_ellipsis);
« no previous file with comments | « ui/gfx/text_elider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698