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

Side by Side Diff: ui/gfx/text_elider.cc

Issue 1070223004: Stop combining text runs which are connected by 'COMMON' blocks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address msw@'s comments. Created 5 years, 6 months 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
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"
11 11
12 #include <stdint.h> 12 #include <stdint.h>
13 13
14 #include <string> 14 #include <string>
15 #include <vector> 15 #include <vector>
16 16
17 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
18 #include "base/i18n/break_iterator.h" 18 #include "base/i18n/break_iterator.h"
19 #include "base/i18n/char_iterator.h" 19 #include "base/i18n/char_iterator.h"
20 #include "base/i18n/rtl.h" 20 #include "base/i18n/rtl.h"
21 #include "base/memory/scoped_ptr.h" 21 #include "base/memory/scoped_ptr.h"
22 #include "base/numerics/safe_conversions.h" 22 #include "base/numerics/safe_conversions.h"
23 #include "base/strings/string_split.h" 23 #include "base/strings/string_split.h"
24 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
25 #include "base/strings/sys_string_conversions.h" 25 #include "base/strings/sys_string_conversions.h"
26 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
27 #include "third_party/icu/source/common/unicode/rbbi.h" 27 #include "third_party/icu/source/common/unicode/rbbi.h"
28 #include "third_party/icu/source/common/unicode/uchar.h" 28 #include "third_party/icu/source/common/unicode/uchar.h"
msw 2015/06/03 00:32:03 nit: can we remove some includes, like this one, n
xdai1 2015/06/06 00:05:19 Done.
29 #include "third_party/icu/source/common/unicode/uloc.h" 29 #include "third_party/icu/source/common/unicode/uloc.h"
30 #include "third_party/icu/source/common/unicode/umachine.h" 30 #include "third_party/icu/source/common/unicode/umachine.h"
31 #include "third_party/icu/source/common/unicode/utf16.h" 31 #include "third_party/icu/source/common/unicode/utf16.h"
msw 2015/06/03 00:32:03 ditto
xdai1 2015/06/06 00:05:19 Done.
32 #include "ui/gfx/font_list.h" 32 #include "ui/gfx/font_list.h"
33 #include "ui/gfx/geometry/rect_conversions.h" 33 #include "ui/gfx/geometry/rect_conversions.h"
34 #include "ui/gfx/render_text.h" 34 #include "ui/gfx/render_text.h"
35 #include "ui/gfx/text_utils.h" 35 #include "ui/gfx/text_utils.h"
36 36
37 using base::ASCIIToUTF16; 37 using base::ASCIIToUTF16;
38 using base::UTF8ToUTF16; 38 using base::UTF8ToUTF16;
39 using base::WideToUTF16; 39 using base::WideToUTF16;
40 40
41 namespace gfx { 41 namespace gfx {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 97
98 // Fit the username in the remaining width (at this point the elided username 98 // Fit the username in the remaining width (at this point the elided username
99 // is guaranteed to fit with at least one character remaining given all the 99 // is guaranteed to fit with at least one character remaining given all the
100 // precautions taken earlier). 100 // precautions taken earlier).
101 available_pixel_width -= GetStringWidthF(domain, font_list); 101 available_pixel_width -= GetStringWidthF(domain, font_list);
102 username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL); 102 username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL);
103 return username + kAtSignUTF16 + domain; 103 return username + kAtSignUTF16 + domain;
104 } 104 }
105 #endif 105 #endif
106 106
107 // Returns true if the code point |c| is a combining mark character in Unicode.
108 bool CharIsMark(UChar32 c) {
109 int8_t char_type = u_charType(c);
110 return char_type == U_NON_SPACING_MARK || char_type == U_ENCLOSING_MARK ||
111 char_type == U_COMBINING_SPACING_MARK;
112 }
113
114 // Gets the code point of |str| at the given code unit position |index|. If
115 // |index| is a surrogate code unit, returns the whole code point (unless the
116 // code unit is unpaired, in which case it just returns the surrogate value).
117 UChar32 GetCodePointAt(const base::string16& str, size_t index) {
118 UChar32 c;
119 U16_GET(str.data(), 0, index, str.size(), c);
120 return c;
121 }
122
123 } // namespace 107 } // namespace
124 108
125 // U+2026 in utf8 109 // U+2026 in utf8
126 const char kEllipsis[] = "\xE2\x80\xA6"; 110 const char kEllipsis[] = "\xE2\x80\xA6";
127 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; 111 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
128 const base::char16 kForwardSlash = '/'; 112 const base::char16 kForwardSlash = '/';
129 113
130 StringSlicer::StringSlicer(const base::string16& text, 114 StringSlicer::StringSlicer(const base::string16& text,
131 const base::string16& ellipsis, 115 const base::string16& ellipsis,
132 bool elide_in_middle, 116 bool elide_in_middle,
133 bool elide_at_beginning) 117 bool elide_at_beginning)
134 : text_(text), 118 : text_(text),
135 ellipsis_(ellipsis), 119 ellipsis_(ellipsis),
136 elide_in_middle_(elide_in_middle), 120 elide_in_middle_(elide_in_middle),
137 elide_at_beginning_(elide_at_beginning) { 121 elide_at_beginning_(elide_at_beginning) {
138 } 122 }
139 123
140 base::string16 StringSlicer::CutString(size_t length, 124 base::string16 StringSlicer::CutString(size_t length,
141 bool insert_ellipsis) const { 125 bool insert_ellipsis) const {
142 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_ 126 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
143 : base::string16(); 127 : base::string16();
144 128
145 if (elide_at_beginning_) 129 if (elide_at_beginning_)
146 return ellipsis_text + 130 return ellipsis_text +
147 text_.substr(FindValidBoundaryBefore(text_.length() - length)); 131 text_.substr(
132 FindValidBoundaryBefore(text_, text_.length() - length));
148 133
149 if (!elide_in_middle_) 134 if (!elide_in_middle_)
150 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; 135 return text_.substr(0, FindValidBoundaryBefore(text_, length)) +
136 ellipsis_text;
151 137
152 // We put the extra character, if any, before the cut. 138 // We put the extra character, if any, before the cut.
153 const size_t half_length = length / 2; 139 const size_t half_length = length / 2;
154 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); 140 const size_t prefix_length =
141 FindValidBoundaryBefore(text_, length - half_length);
155 const size_t suffix_start = 142 const size_t suffix_start =
156 FindValidBoundaryAfter(text_.length() - half_length); 143 FindValidBoundaryAfter(text_, text_.length() - half_length);
157 return text_.substr(0, prefix_length) + ellipsis_text + 144 return text_.substr(0, prefix_length) + ellipsis_text +
158 text_.substr(suffix_start); 145 text_.substr(suffix_start);
159 } 146 }
160 147
161 size_t StringSlicer::FindValidBoundaryBefore(size_t index) const {
162 size_t length = text_.length();
163 DCHECK_LE(index, length);
164 if (index == length)
165 return index;
166
167 // If |index| straddles a combining character sequence, go back until we find
168 // a base character.
169 while (index > 0 && CharIsMark(GetCodePointAt(text_, index)))
170 --index;
171
172 // If |index| straddles a UTF-16 surrogate pair, go back.
173 U16_SET_CP_START(text_.data(), 0, index);
174 return index;
175 }
176
177 size_t StringSlicer::FindValidBoundaryAfter(size_t index) const {
178 DCHECK_LE(index, text_.length());
179 if (index == text_.length())
180 return index;
181
182 int32_t text_index = base::checked_cast<int32_t>(index);
183 int32_t text_length = base::checked_cast<int32_t>(text_.length());
184
185 // If |index| straddles a combining character sequence, go forward until we
186 // find a base character.
187 while (text_index < text_length &&
188 CharIsMark(GetCodePointAt(text_, text_index))) {
189 ++text_index;
190 }
191
192 // If |index| straddles a UTF-16 surrogate pair, go forward.
193 U16_SET_CP_LIMIT(text_.data(), 0, text_index, text_length);
194 return static_cast<size_t>(text_index);
195 }
196
197 base::string16 ElideFilename(const base::FilePath& filename, 148 base::string16 ElideFilename(const base::FilePath& filename,
198 const FontList& font_list, 149 const FontList& font_list,
199 float available_pixel_width) { 150 float available_pixel_width) {
200 #if defined(OS_WIN) 151 #if defined(OS_WIN)
201 base::string16 filename_utf16 = filename.value(); 152 base::string16 filename_utf16 = filename.value();
202 base::string16 extension = filename.Extension(); 153 base::string16 extension = filename.Extension();
203 base::string16 rootname = filename.BaseName().RemoveExtension().value(); 154 base::string16 rootname = filename.BaseName().RemoveExtension().value();
204 #elif defined(OS_POSIX) 155 #elif defined(OS_POSIX)
205 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( 156 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide(
206 filename.value())); 157 filename.value()));
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 index = char_iterator.getIndex(); 812 index = char_iterator.getIndex();
862 } else { 813 } else {
863 // String has leading whitespace, return the elide string. 814 // String has leading whitespace, return the elide string.
864 return kElideString; 815 return kElideString;
865 } 816 }
866 817
867 return string.substr(0, index) + kElideString; 818 return string.substr(0, index) + kElideString;
868 } 819 }
869 820
870 } // namespace gfx 821 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698