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

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: Fix broken unittest. 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"
23 #include "base/strings/string_split.h" 22 #include "base/strings/string_split.h"
24 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
25 #include "base/strings/sys_string_conversions.h" 24 #include "base/strings/sys_string_conversions.h"
26 #include "base/strings/utf_string_conversions.h" 25 #include "base/strings/utf_string_conversions.h"
27 #include "third_party/icu/source/common/unicode/rbbi.h" 26 #include "third_party/icu/source/common/unicode/rbbi.h"
28 #include "third_party/icu/source/common/unicode/uchar.h"
29 #include "third_party/icu/source/common/unicode/uloc.h" 27 #include "third_party/icu/source/common/unicode/uloc.h"
30 #include "third_party/icu/source/common/unicode/umachine.h" 28 #include "third_party/icu/source/common/unicode/umachine.h"
31 #include "third_party/icu/source/common/unicode/utf16.h"
32 #include "ui/gfx/font_list.h" 29 #include "ui/gfx/font_list.h"
33 #include "ui/gfx/geometry/rect_conversions.h" 30 #include "ui/gfx/geometry/rect_conversions.h"
34 #include "ui/gfx/render_text.h" 31 #include "ui/gfx/render_text.h"
35 #include "ui/gfx/text_utils.h" 32 #include "ui/gfx/text_utils.h"
36 33
37 using base::ASCIIToUTF16; 34 using base::ASCIIToUTF16;
38 using base::UTF8ToUTF16; 35 using base::UTF8ToUTF16;
39 using base::WideToUTF16; 36 using base::WideToUTF16;
40 37
41 namespace gfx { 38 namespace gfx {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 94
98 // Fit the username in the remaining width (at this point the elided username 95 // 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 96 // is guaranteed to fit with at least one character remaining given all the
100 // precautions taken earlier). 97 // precautions taken earlier).
101 available_pixel_width -= GetStringWidthF(domain, font_list); 98 available_pixel_width -= GetStringWidthF(domain, font_list);
102 username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL); 99 username = ElideText(username, font_list, available_pixel_width, ELIDE_TAIL);
103 return username + kAtSignUTF16 + domain; 100 return username + kAtSignUTF16 + domain;
104 } 101 }
105 #endif 102 #endif
106 103
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 104 } // namespace
124 105
125 // U+2026 in utf8 106 // U+2026 in utf8
126 const char kEllipsis[] = "\xE2\x80\xA6"; 107 const char kEllipsis[] = "\xE2\x80\xA6";
127 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 }; 108 const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
128 const base::char16 kForwardSlash = '/'; 109 const base::char16 kForwardSlash = '/';
129 110
130 StringSlicer::StringSlicer(const base::string16& text, 111 StringSlicer::StringSlicer(const base::string16& text,
131 const base::string16& ellipsis, 112 const base::string16& ellipsis,
132 bool elide_in_middle, 113 bool elide_in_middle,
133 bool elide_at_beginning) 114 bool elide_at_beginning)
134 : text_(text), 115 : text_(text),
135 ellipsis_(ellipsis), 116 ellipsis_(ellipsis),
136 elide_in_middle_(elide_in_middle), 117 elide_in_middle_(elide_in_middle),
137 elide_at_beginning_(elide_at_beginning) { 118 elide_at_beginning_(elide_at_beginning) {
138 } 119 }
139 120
140 base::string16 StringSlicer::CutString(size_t length, 121 base::string16 StringSlicer::CutString(size_t length,
141 bool insert_ellipsis) const { 122 bool insert_ellipsis) const {
142 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_ 123 const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
143 : base::string16(); 124 : base::string16();
144 125
145 if (elide_at_beginning_) 126 if (elide_at_beginning_)
146 return ellipsis_text + 127 return ellipsis_text +
147 text_.substr(FindValidBoundaryBefore(text_.length() - length)); 128 text_.substr(
129 FindValidBoundaryBefore(text_, text_.length() - length));
148 130
149 if (!elide_in_middle_) 131 if (!elide_in_middle_)
150 return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text; 132 return text_.substr(0, FindValidBoundaryBefore(text_, length)) +
133 ellipsis_text;
151 134
152 // We put the extra character, if any, before the cut. 135 // We put the extra character, if any, before the cut.
153 const size_t half_length = length / 2; 136 const size_t half_length = length / 2;
154 const size_t prefix_length = FindValidBoundaryBefore(length - half_length); 137 const size_t prefix_length =
138 FindValidBoundaryBefore(text_, length - half_length);
155 const size_t suffix_start = 139 const size_t suffix_start =
156 FindValidBoundaryAfter(text_.length() - half_length); 140 FindValidBoundaryAfter(text_, text_.length() - half_length);
157 return text_.substr(0, prefix_length) + ellipsis_text + 141 return text_.substr(0, prefix_length) + ellipsis_text +
158 text_.substr(suffix_start); 142 text_.substr(suffix_start);
159 } 143 }
160 144
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, 145 base::string16 ElideFilename(const base::FilePath& filename,
198 const FontList& font_list, 146 const FontList& font_list,
199 float available_pixel_width) { 147 float available_pixel_width) {
200 #if defined(OS_WIN) 148 #if defined(OS_WIN)
201 base::string16 filename_utf16 = filename.value(); 149 base::string16 filename_utf16 = filename.value();
202 base::string16 extension = filename.Extension(); 150 base::string16 extension = filename.Extension();
203 base::string16 rootname = filename.BaseName().RemoveExtension().value(); 151 base::string16 rootname = filename.BaseName().RemoveExtension().value();
204 #elif defined(OS_POSIX) 152 #elif defined(OS_POSIX)
205 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( 153 base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide(
206 filename.value())); 154 filename.value()));
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 index = char_iterator.getIndex(); 809 index = char_iterator.getIndex();
862 } else { 810 } else {
863 // String has leading whitespace, return the elide string. 811 // String has leading whitespace, return the elide string.
864 return kElideString; 812 return kElideString;
865 } 813 }
866 814
867 return string.substr(0, index) + kElideString; 815 return string.substr(0, index) + kElideString;
868 } 816 }
869 817
870 } // namespace gfx 818 } // namespace gfx
OLDNEW
« ui/gfx/render_text_unittest.cc ('K') | « ui/gfx/text_elider.h ('k') | ui/gfx/text_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698