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

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

Issue 312233003: Add fade eliding for Views Labels; related cleanup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refine alignment check; minor additional cleanup. Created 6 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 | Annotate | Revision Log
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/gfx/render_text.h » ('j') | 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 #include "ui/gfx/canvas.h" 5 #include "ui/gfx/canvas.h"
6 6
7 #include "base/i18n/rtl.h" 7 #include "base/i18n/rtl.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "ui/gfx/font_list.h" 10 #include "ui/gfx/font_list.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 *bitmap.getAddr32(x, y - 1) != 0) 77 *bitmap.getAddr32(x, y - 1) != 0)
78 return true; // Touched pixel above. 78 return true; // Touched pixel above.
79 if (y < bitmap.height() - 1 && 79 if (y < bitmap.height() - 1 &&
80 *bitmap.getAddr32(x, y + 1) != halo_color && 80 *bitmap.getAddr32(x, y + 1) != halo_color &&
81 *bitmap.getAddr32(x, y + 1) != 0) 81 *bitmap.getAddr32(x, y + 1) != 0)
82 return true; // Touched pixel below. 82 return true; // Touched pixel below.
83 return false; 83 return false;
84 } 84 }
85 85
86 // Strips accelerator character prefixes in |text| if needed, based on |flags|. 86 // Strips accelerator character prefixes in |text| if needed, based on |flags|.
87 // Returns a range in |text| to underline or gfx::Range::InvalidRange() if 87 // Returns a range in |text| to underline or Range::InvalidRange() if
88 // underlining is not needed. 88 // underlining is not needed.
89 Range StripAcceleratorChars(int flags, base::string16* text) { 89 Range StripAcceleratorChars(int flags, base::string16* text) {
90 if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) { 90 if (flags & (Canvas::SHOW_PREFIX | Canvas::HIDE_PREFIX)) {
91 int char_pos = -1; 91 int char_pos = -1;
92 int char_span = 0; 92 int char_span = 0;
93 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span); 93 *text = RemoveAcceleratorChar(*text, '&', &char_pos, &char_span);
94 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1) 94 if ((flags & Canvas::SHOW_PREFIX) && char_pos != -1)
95 return Range(char_pos, char_pos + char_span); 95 return Range(char_pos, char_pos + char_span);
96 } 96 }
97 return Range::InvalidRange(); 97 return Range::InvalidRange();
98 } 98 }
99 99
100 // Elides |text| and adjusts |range| appropriately. If eliding causes |range| 100 // Elides |text| and adjusts |range| appropriately. If eliding causes |range|
101 // to no longer point to the same character in |text|, |range| is made invalid. 101 // to no longer point to the same character in |text|, |range| is made invalid.
102 void ElideTextAndAdjustRange(const FontList& font_list, 102 void ElideTextAndAdjustRange(const FontList& font_list,
103 int width, 103 int width,
104 base::string16* text, 104 base::string16* text,
105 Range* range) { 105 Range* range) {
106 const base::char16 start_char = 106 const base::char16 start_char =
107 (range->IsValid() ? text->at(range->start()) : 0); 107 (range->IsValid() ? text->at(range->start()) : 0);
108 *text = gfx::ElideText(*text, font_list, width, gfx::ELIDE_AT_END); 108 *text = ElideText(*text, font_list, width, ELIDE_TAIL);
109 if (!range->IsValid()) 109 if (!range->IsValid())
110 return; 110 return;
111 if (range->start() >= text->length() || 111 if (range->start() >= text->length() ||
112 text->at(range->start()) != start_char) { 112 text->at(range->start()) != start_char) {
113 *range = Range::InvalidRange(); 113 *range = Range::InvalidRange();
114 } 114 }
115 } 115 }
116 116
117 // Updates |render_text| from the specified parameters. 117 // Updates |render_text| from the specified parameters.
118 void UpdateRenderText(const Rect& rect, 118 void UpdateRenderText(const Rect& rect,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 int flags) { 164 int flags) {
165 DCHECK_GE(*width, 0); 165 DCHECK_GE(*width, 0);
166 DCHECK_GE(*height, 0); 166 DCHECK_GE(*height, 0);
167 167
168 base::string16 adjusted_text = text; 168 base::string16 adjusted_text = text;
169 #if defined(OS_WIN) 169 #if defined(OS_WIN)
170 AdjustStringDirection(flags, &adjusted_text); 170 AdjustStringDirection(flags, &adjusted_text);
171 #endif 171 #endif
172 172
173 if ((flags & MULTI_LINE) && *width != 0) { 173 if ((flags & MULTI_LINE) && *width != 0) {
174 gfx::WordWrapBehavior wrap_behavior = gfx::TRUNCATE_LONG_WORDS; 174 WordWrapBehavior wrap_behavior = TRUNCATE_LONG_WORDS;
175 if (flags & CHARACTER_BREAK) 175 if (flags & CHARACTER_BREAK)
176 wrap_behavior = gfx::WRAP_LONG_WORDS; 176 wrap_behavior = WRAP_LONG_WORDS;
177 else if (!(flags & NO_ELLIPSIS)) 177 else if (!(flags & NO_ELLIPSIS))
178 wrap_behavior = gfx::ELIDE_LONG_WORDS; 178 wrap_behavior = ELIDE_LONG_WORDS;
179 179
180 Rect rect(*width, INT_MAX); 180 Rect rect(*width, INT_MAX);
181 std::vector<base::string16> strings; 181 std::vector<base::string16> strings;
182 gfx::ElideRectangleText(adjusted_text, font_list, 182 ElideRectangleText(adjusted_text, font_list, rect.width(), rect.height(),
183 rect.width(), rect.height(), 183 wrap_behavior, &strings);
184 wrap_behavior, &strings);
185 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 184 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
186 UpdateRenderText(rect, base::string16(), font_list, flags, 0, 185 UpdateRenderText(rect, base::string16(), font_list, flags, 0,
187 render_text.get()); 186 render_text.get());
188 187
189 float h = 0; 188 float h = 0;
190 float w = 0; 189 float w = 0;
191 for (size_t i = 0; i < strings.size(); ++i) { 190 for (size_t i = 0; i < strings.size(); ++i) {
192 StripAcceleratorChars(flags, &strings[i]); 191 StripAcceleratorChars(flags, &strings[i]);
193 render_text->SetText(strings[i]); 192 render_text->SetText(strings[i]);
194 const SizeF& string_size = render_text->GetStringSizeF(); 193 const SizeF& string_size = render_text->GetStringSizeF();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 base::string16 adjusted_text = text; 236 base::string16 adjusted_text = text;
238 237
239 #if defined(OS_WIN) 238 #if defined(OS_WIN)
240 AdjustStringDirection(flags, &adjusted_text); 239 AdjustStringDirection(flags, &adjusted_text);
241 #endif 240 #endif
242 241
243 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 242 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
244 render_text->SetTextShadows(shadows); 243 render_text->SetTextShadows(shadows);
245 244
246 if (flags & MULTI_LINE) { 245 if (flags & MULTI_LINE) {
247 gfx::WordWrapBehavior wrap_behavior = gfx::IGNORE_LONG_WORDS; 246 WordWrapBehavior wrap_behavior = IGNORE_LONG_WORDS;
248 if (flags & CHARACTER_BREAK) 247 if (flags & CHARACTER_BREAK)
249 wrap_behavior = gfx::WRAP_LONG_WORDS; 248 wrap_behavior = WRAP_LONG_WORDS;
250 else if (!(flags & NO_ELLIPSIS)) 249 else if (!(flags & NO_ELLIPSIS))
251 wrap_behavior = gfx::ELIDE_LONG_WORDS; 250 wrap_behavior = ELIDE_LONG_WORDS;
252 251
253 std::vector<base::string16> strings; 252 std::vector<base::string16> strings;
254 gfx::ElideRectangleText(adjusted_text, 253 ElideRectangleText(adjusted_text, font_list, text_bounds.width(),
255 font_list, 254 text_bounds.height(), wrap_behavior, &strings);
256 text_bounds.width(), text_bounds.height(),
257 wrap_behavior,
258 &strings);
259 255
260 for (size_t i = 0; i < strings.size(); i++) { 256 for (size_t i = 0; i < strings.size(); i++) {
261 Range range = StripAcceleratorChars(flags, &strings[i]); 257 Range range = StripAcceleratorChars(flags, &strings[i]);
262 UpdateRenderText(rect, strings[i], font_list, flags, color, 258 UpdateRenderText(rect, strings[i], font_list, flags, color,
263 render_text.get()); 259 render_text.get());
264 int line_padding = 0; 260 int line_padding = 0;
265 if (line_height > 0) 261 if (line_height > 0)
266 line_padding = line_height - render_text->GetStringSize().height(); 262 line_padding = line_height - render_text->GetStringSize().height();
267 else 263 else
268 line_height = render_text->GetStringSize().height(); 264 line_height = render_text->GetStringSize().height();
(...skipping 18 matching lines...) Expand all
287 } else { 283 } else {
288 Range range = StripAcceleratorChars(flags, &adjusted_text); 284 Range range = StripAcceleratorChars(flags, &adjusted_text);
289 bool elide_text = ((flags & NO_ELLIPSIS) == 0); 285 bool elide_text = ((flags & NO_ELLIPSIS) == 0);
290 286
291 #if defined(OS_LINUX) 287 #if defined(OS_LINUX)
292 // On Linux, eliding really means fading the end of the string. But only 288 // On Linux, eliding really means fading the end of the string. But only
293 // for LTR text. RTL text is still elided (on the left) with "...". 289 // for LTR text. RTL text is still elided (on the left) with "...".
294 if (elide_text) { 290 if (elide_text) {
295 render_text->SetText(adjusted_text); 291 render_text->SetText(adjusted_text);
296 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { 292 if (render_text->GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
297 render_text->set_fade_tail(true); 293 render_text->SetElideBehavior(FADE_TAIL);
298 elide_text = false; 294 elide_text = false;
299 } 295 }
300 } 296 }
301 #endif 297 #endif
302 298
303 if (elide_text) { 299 if (elide_text) {
304 ElideTextAndAdjustRange(font_list, 300 ElideTextAndAdjustRange(font_list, text_bounds.width(), &adjusted_text,
305 text_bounds.width(),
306 &adjusted_text,
307 &range); 301 &range);
308 } 302 }
309 303
310 UpdateRenderText(rect, adjusted_text, font_list, flags, color, 304 UpdateRenderText(rect, adjusted_text, font_list, flags, color,
311 render_text.get()); 305 render_text.get());
312 306
313 const int text_height = render_text->GetStringSize().height(); 307 const int text_height = render_text->GetStringSize().height();
314 // Center the text vertically.
315 rect += Vector2d(0, (text_bounds.height() - text_height) / 2); 308 rect += Vector2d(0, (text_bounds.height() - text_height) / 2);
316 rect.set_height(text_height); 309 rect.set_height(text_height);
317 render_text->SetDisplayRect(rect); 310 render_text->SetDisplayRect(rect);
318 if (range.IsValid()) 311 if (range.IsValid())
319 render_text->ApplyStyle(UNDERLINE, true, range); 312 render_text->ApplyStyle(UNDERLINE, true, range);
320 render_text->Draw(this); 313 render_text->Draw(this);
321 } 314 }
322 315
323 canvas_->restore(); 316 canvas_->restore();
324 } 317 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 357 }
365 } 358 }
366 } 359 }
367 360
368 // Draw the halo bitmap with blur. 361 // Draw the halo bitmap with blur.
369 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap, 362 ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap,
370 text_canvas.image_scale())); 363 text_canvas.image_scale()));
371 DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1); 364 DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1);
372 } 365 }
373 366
374 void Canvas::DrawFadeTruncatingStringRect( 367 void Canvas::DrawFadedString(const base::string16& text,
375 const base::string16& text, 368 const FontList& font_list,
376 TruncateFadeMode truncate_mode, 369 SkColor color,
377 const FontList& font_list, 370 const Rect& display_rect,
378 SkColor color, 371 int flags) {
379 const Rect& display_rect) {
380 DrawFadeTruncatingStringRectWithFlags(
381 text, truncate_mode, font_list, color, display_rect, NO_ELLIPSIS);
382 }
383
384 void Canvas::DrawFadeTruncatingStringRectWithFlags(
385 const base::string16& text,
386 TruncateFadeMode truncate_mode,
387 const FontList& font_list,
388 SkColor color,
389 const Rect& display_rect,
390 int flags) {
391 // If the whole string fits in the destination then just draw it directly. 372 // If the whole string fits in the destination then just draw it directly.
392 if (GetStringWidth(text, font_list) <= display_rect.width()) { 373 if (GetStringWidth(text, font_list) <= display_rect.width()) {
393 DrawStringRectWithFlags(text, font_list, color, display_rect, flags); 374 DrawStringRectWithFlags(text, font_list, color, display_rect, flags);
394 return; 375 return;
395 } 376 }
396 377
378 // Align to content directionality instead of centering and fading both ends.
379 if (!(flags & TEXT_ALIGN_LEFT) && !(flags & TEXT_ALIGN_RIGHT)) {
380 flags &= ~TEXT_ALIGN_CENTER;
381 const bool is_rtl = base::i18n::GetFirstStrongCharacterDirection(text) ==
382 base::i18n::RIGHT_TO_LEFT;
383 flags |= is_rtl ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT;
384 }
385 flags |= NO_ELLIPSIS;
386
397 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); 387 scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
398 const bool is_rtl = base::i18n::GetFirstStrongCharacterDirection(text) ==
399 base::i18n::RIGHT_TO_LEFT;
400
401 switch (truncate_mode) {
402 case TruncateFadeTail:
403 render_text->set_fade_tail(true);
404 if (is_rtl)
405 flags |= TEXT_ALIGN_RIGHT;
406 break;
407 case TruncateFadeHead:
408 render_text->set_fade_head(true);
409 if (!is_rtl)
410 flags |= TEXT_ALIGN_RIGHT;
411 break;
412 }
413
414 // Default to left alignment unless right alignment was chosen above.
415 if (!(flags & TEXT_ALIGN_RIGHT))
416 flags |= TEXT_ALIGN_LEFT;
417
418 Rect rect = display_rect; 388 Rect rect = display_rect;
419 UpdateRenderText(rect, text, font_list, flags, color, render_text.get()); 389 UpdateRenderText(rect, text, font_list, flags, color, render_text.get());
390 render_text->SetElideBehavior(FADE_TAIL);
420 391
421 const int line_height = render_text->GetStringSize().height(); 392 const int line_height = render_text->GetStringSize().height();
422 // Center the text vertically.
423 rect += Vector2d(0, (display_rect.height() - line_height) / 2); 393 rect += Vector2d(0, (display_rect.height() - line_height) / 2);
424 rect.set_height(line_height); 394 rect.set_height(line_height);
425 render_text->SetDisplayRect(rect); 395 render_text->SetDisplayRect(rect);
426 396
427 canvas_->save(); 397 canvas_->save();
428 ClipRect(display_rect); 398 ClipRect(display_rect);
429 render_text->Draw(this); 399 render_text->Draw(this);
430 canvas_->restore(); 400 canvas_->restore();
431 } 401 }
432 402
433 } // namespace gfx 403 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/gfx/render_text.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698