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

Side by Side 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: 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 unified diff | Download patch
« ui/gfx/text_elider.h ('K') | « ui/gfx/text_elider.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements utility functions for eliding and formatting UI text. 5 // This file implements utility functions for eliding and formatting UI text.
6 // 6 //
7 // Note that several of the functions declared in text_elider.h are implemented 7 // Note that several of the functions declared in text_elider.h are implemented
8 // in this file using helper classes in an unnamed namespace. 8 // in this file using helper classes in an unnamed namespace.
9 9
10 #include "ui/gfx/text_elider.h" 10 #include "ui/gfx/text_elider.h"
(...skipping 21 matching lines...) Expand all
32 32
33 namespace gfx { 33 namespace gfx {
34 34
35 // U+2026 in utf8 35 // U+2026 in utf8
36 const char kEllipsis[] = "\xE2\x80\xA6"; 36 const char kEllipsis[] = "\xE2\x80\xA6";
37 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; 37 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
38 const base::char16 kForwardSlash = '/'; 38 const base::char16 kForwardSlash = '/';
39 39
40 namespace { 40 namespace {
41 41
42 // Helper class to split + elide text, while respecting UTF16 surrogate pairs.
43 class StringSlicer {
44 public:
45 StringSlicer(const base::string16& text,
46 const base::string16& ellipsis,
47 bool elide_in_middle)
48 : text_(text),
49 ellipsis_(ellipsis),
50 elide_in_middle_(elide_in_middle) {
51 }
52
53 // Cuts |text_| to be |length| characters long. If |elide_in_middle_| is true,
54 // the middle of the string is removed to leave equal-length pieces from the
55 // beginning and end of the string; otherwise, the end of the string is
56 // removed and only the beginning remains. If |insert_ellipsis| is true,
57 // then an ellipsis character will be inserted at the cut point.
58 base::string16 CutString(size_t length, bool insert_ellipsis) {
59 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
60 : base::string16();
61
62 if (!elide_in_middle_)
63 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text;
64
65 // We put the extra character, if any, before the cut.
66 const size_t half_length = length / 2;
67 const size_t prefix_length = FindValidBoundaryBefore(length - half_length);
68 const size_t suffix_start_guess = text_.length() - half_length;
69 const size_t suffix_start = FindValidBoundaryAfter(suffix_start_guess);
70 const size_t suffix_length =
71 half_length - (suffix_start_guess - suffix_start);
72 return text_.substr(0, prefix_length) + ellipsis_text +
73 text_.substr(suffix_start, suffix_length);
74 }
75
76 private:
77 // Returns a valid cut boundary at or before |index|.
78 size_t FindValidBoundaryBefore(size_t index) const {
79 DCHECK_LE(index, text_.length());
80 if (index != text_.length())
81 U16_SET_CP_START(text_.data(), 0, index);
82 return index;
83 }
84
85 // Returns a valid cut boundary at or after |index|.
86 size_t FindValidBoundaryAfter(size_t index) const {
87 DCHECK_LE(index, text_.length());
88 if (index != text_.length())
89 U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length());
90 return index;
91 }
92
93 // The text to be sliced.
94 const base::string16& text_;
95
96 // Ellipsis string to use.
97 const base::string16& ellipsis_;
98
99 // If true, the middle of the string will be elided.
100 bool elide_in_middle_;
101
102 DISALLOW_COPY_AND_ASSIGN(StringSlicer);
103 };
104 42
105 // Build a path from the first |num_components| elements in |path_elements|. 43 // Build a path from the first |num_components| elements in |path_elements|.
106 // Prepends |path_prefix|, appends |filename|, inserts ellipsis if appropriate. 44 // Prepends |path_prefix|, appends |filename|, inserts ellipsis if appropriate.
107 base::string16 BuildPathFromComponents( 45 base::string16 BuildPathFromComponents(
108 const base::string16& path_prefix, 46 const base::string16& path_prefix,
109 const std::vector<base::string16>& path_elements, 47 const std::vector<base::string16>& path_elements,
110 const base::string16& filename, 48 const base::string16& filename,
111 size_t num_components) { 49 size_t num_components) {
112 // Add the initial elements of the path. 50 // Add the initial elements of the path.
113 base::string16 path = path_prefix; 51 base::string16 path = path_prefix;
(...skipping 29 matching lines...) Expand all
143 if (available_pixel_width >= GetStringWidthF(elided_path, font_list)) 81 if (available_pixel_width >= GetStringWidthF(elided_path, font_list))
144 return ElideText(elided_path + url_query, font_list, 82 return ElideText(elided_path + url_query, font_list,
145 available_pixel_width, ELIDE_AT_END); 83 available_pixel_width, ELIDE_AT_END);
146 } 84 }
147 85
148 return base::string16(); 86 return base::string16();
149 } 87 }
150 88
151 } // namespace 89 } // namespace
152 90
91 StringSlicer::StringSlicer(const base::string16& text,
92 const base::string16& ellipsis,
93 bool elide_in_middle)
94 : text_(text),
95 ellipsis_(ellipsis),
96 elide_in_middle_(elide_in_middle) {
97 }
98
99 base::string16 StringSlicer::CutString(size_t length, bool insert_ellipsis) {
100 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
101 : base::string16();
102
103 if (!elide_in_middle_)
104 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text;
105
106 // We put the extra character, if any, before the cut.
107 const size_t half_length = length / 2;
108 const size_t prefix_length = FindValidBoundaryBefore(length - half_length);
109 const size_t suffix_start_guess = text_.length() - half_length;
110 const size_t suffix_start = FindValidBoundaryAfter(suffix_start_guess);
111 const size_t suffix_length =
112 half_length - (suffix_start_guess - suffix_start);
113 return text_.substr(0, prefix_length) + ellipsis_text +
114 text_.substr(suffix_start, suffix_length);
115 }
116
117 size_t StringSlicer::FindValidBoundaryBefore(size_t index) const {
118 DCHECK_LE(index, text_.length());
119 if (index != text_.length())
120 U16_SET_CP_START(text_.data(), 0, index);
121 return index;
122 }
123
124 size_t StringSlicer::FindValidBoundaryAfter(size_t index) const {
125 DCHECK_LE(index, text_.length());
126 if (index != text_.length())
127 U16_SET_CP_LIMIT(text_.data(), 0, index, text_.length());
128 return index;
129 }
130
153 base::string16 ElideEmail(const base::string16& email, 131 base::string16 ElideEmail(const base::string16& email,
154 const FontList& font_list, 132 const FontList& font_list,
155 float available_pixel_width) { 133 float available_pixel_width) {
156 if (GetStringWidthF(email, font_list) <= available_pixel_width) 134 if (GetStringWidthF(email, font_list) <= available_pixel_width)
157 return email; 135 return email;
158 136
159 // Split the email into its local-part (username) and domain-part. The email 137 // Split the email into its local-part (username) and domain-part. The email
160 // spec technically allows for @ symbols in the local-part (username) of the 138 // spec technically allows for @ symbols in the local-part (username) of the
161 // email under some special requirements. It is guaranteed that there is no @ 139 // email under some special requirements. It is guaranteed that there is no @
162 // symbol in the domain part of the email however so splitting at the last @ 140 // symbol in the domain part of the email however so splitting at the last @
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 index = char_iterator.getIndex(); 1116 index = char_iterator.getIndex();
1139 } else { 1117 } else {
1140 // String has leading whitespace, return the elide string. 1118 // String has leading whitespace, return the elide string.
1141 return kElideString; 1119 return kElideString;
1142 } 1120 }
1143 } 1121 }
1144 return string.substr(0, index) + kElideString; 1122 return string.substr(0, index) + kElideString;
1145 } 1123 }
1146 1124
1147 } // namespace gfx 1125 } // namespace gfx
OLDNEW
« ui/gfx/text_elider.h ('K') | « ui/gfx/text_elider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698