Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/render_text.h" | 5 #include "ui/gfx/render_text.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | |
| 8 | 9 |
| 9 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 12 #include "third_party/icu/source/common/unicode/rbbi.h" | 13 #include "third_party/icu/source/common/unicode/rbbi.h" |
| 13 #include "third_party/icu/source/common/unicode/utf16.h" | 14 #include "third_party/icu/source/common/unicode/utf16.h" |
| 14 #include "third_party/skia/include/core/SkTypeface.h" | 15 #include "third_party/skia/include/core/SkTypeface.h" |
| 15 #include "third_party/skia/include/effects/SkGradientShader.h" | 16 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 16 #include "ui/gfx/canvas.h" | 17 #include "ui/gfx/canvas.h" |
| 17 #include "ui/gfx/insets.h" | 18 #include "ui/gfx/insets.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 37 | 38 |
| 38 // Fraction of the text size to lower a strike through below the baseline. | 39 // Fraction of the text size to lower a strike through below the baseline. |
| 39 const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 6 / 21); | 40 const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 6 / 21); |
| 40 // Fraction of the text size to lower an underline below the baseline. | 41 // Fraction of the text size to lower an underline below the baseline. |
| 41 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9); | 42 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9); |
| 42 // Fraction of the text size to use for a strike through or under-line. | 43 // Fraction of the text size to use for a strike through or under-line. |
| 43 const SkScalar kLineThickness = (SK_Scalar1 / 18); | 44 const SkScalar kLineThickness = (SK_Scalar1 / 18); |
| 44 // Fraction of the text size to use for a top margin of a diagonal strike. | 45 // Fraction of the text size to use for a top margin of a diagonal strike. |
| 45 const SkScalar kDiagonalStrikeMarginOffset = (SK_Scalar1 / 4); | 46 const SkScalar kDiagonalStrikeMarginOffset = (SK_Scalar1 / 4); |
| 46 | 47 |
| 48 // Invalid value of baseline. Assigning this value to |baseline_| causes | |
| 49 // re-calculation of baseline. | |
| 50 const int kInvalidBaseline = std::numeric_limits<int>::max(); | |
| 51 | |
| 52 // Returns the baseline, with which the text best appears vertically centered. | |
| 53 int DetermineBaselineCenteringText(const Rect& display_rect, | |
| 54 const FontList& font_list) { | |
| 55 const int display_height = display_rect.height(); | |
| 56 const int font_height = font_list.GetHeight(); | |
| 57 // Lower and upper bound of baseline shift as we try to show as much area of | |
| 58 // text as possible. In particular case of |display_height| == |font_height|, | |
| 59 // we do not want to shift the baseline. | |
| 60 int min_shift; | |
| 61 int max_shift; | |
| 62 if (display_height < font_height) { | |
| 63 min_shift = display_height - font_height; | |
| 64 max_shift = font_height - display_height; | |
| 65 } else { | |
| 66 min_shift = 0; | |
| 67 max_shift = display_height - font_height; | |
| 68 } | |
| 69 const int baseline = font_list.GetBaseline(); | |
| 70 const int cap_height = font_list.GetCapHeight(); | |
| 71 const int internal_leading = baseline - cap_height; | |
| 72 const int baseline_shift = | |
| 73 std::max(min_shift, std::min(max_shift, | |
| 74 (display_height - cap_height) / 2 - internal_leading)); | |
| 75 return baseline + baseline_shift; | |
|
Alexei Svitkine (slow)
2013/10/24 15:03:55
Nit: I think this is more readable:
const int b
Yuki
2013/10/24 15:17:36
Done.
| |
| 76 } | |
| 77 | |
| 47 // Converts |gfx::Font::FontStyle| flags to |SkTypeface::Style| flags. | 78 // Converts |gfx::Font::FontStyle| flags to |SkTypeface::Style| flags. |
| 48 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { | 79 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { |
| 49 int skia_style = SkTypeface::kNormal; | 80 int skia_style = SkTypeface::kNormal; |
| 50 skia_style |= (font_style & gfx::Font::BOLD) ? SkTypeface::kBold : 0; | 81 skia_style |= (font_style & gfx::Font::BOLD) ? SkTypeface::kBold : 0; |
| 51 skia_style |= (font_style & gfx::Font::ITALIC) ? SkTypeface::kItalic : 0; | 82 skia_style |= (font_style & gfx::Font::ITALIC) ? SkTypeface::kItalic : 0; |
| 52 return static_cast<SkTypeface::Style>(skia_style); | 83 return static_cast<SkTypeface::Style>(skia_style); |
| 53 } | 84 } |
| 54 | 85 |
| 55 // Given |font| and |display_width|, returns the width of the fade gradient. | 86 // Given |font| and |display_width|, returns the width of the fade gradient. |
| 56 int CalculateFadeGradientWidth(const Font& font, int display_width) { | 87 int CalculateFadeGradientWidth(const Font& font, int display_width) { |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 } | 372 } |
| 342 | 373 |
| 343 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { | 374 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { |
| 344 if (horizontal_alignment_ != alignment) { | 375 if (horizontal_alignment_ != alignment) { |
| 345 horizontal_alignment_ = alignment; | 376 horizontal_alignment_ = alignment; |
| 346 display_offset_ = Vector2d(); | 377 display_offset_ = Vector2d(); |
| 347 cached_bounds_and_offset_valid_ = false; | 378 cached_bounds_and_offset_valid_ = false; |
| 348 } | 379 } |
| 349 } | 380 } |
| 350 | 381 |
| 351 void RenderText::SetVerticalAlignment(VerticalAlignment alignment) { | |
| 352 if (vertical_alignment_ != alignment) { | |
| 353 vertical_alignment_ = alignment; | |
| 354 display_offset_ = Vector2d(); | |
| 355 cached_bounds_and_offset_valid_ = false; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 void RenderText::SetFontList(const FontList& font_list) { | 382 void RenderText::SetFontList(const FontList& font_list) { |
| 360 font_list_ = font_list; | 383 font_list_ = font_list; |
| 384 baseline_ = kInvalidBaseline; | |
| 361 cached_bounds_and_offset_valid_ = false; | 385 cached_bounds_and_offset_valid_ = false; |
| 362 ResetLayout(); | 386 ResetLayout(); |
| 363 } | 387 } |
| 364 | 388 |
| 365 void RenderText::SetFont(const Font& font) { | 389 void RenderText::SetFont(const Font& font) { |
| 366 SetFontList(FontList(font)); | 390 SetFontList(FontList(font)); |
| 367 } | 391 } |
| 368 | 392 |
| 369 void RenderText::SetFontSize(int size) { | 393 void RenderText::SetFontSize(int size) { |
| 370 SetFontList(font_list_.DeriveFontListWithSize(size)); | 394 SetFontList(font_list_.DeriveFontListWithSize(size)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 void RenderText::SetMultiline(bool multiline) { | 431 void RenderText::SetMultiline(bool multiline) { |
| 408 if (multiline != multiline_) { | 432 if (multiline != multiline_) { |
| 409 multiline_ = multiline; | 433 multiline_ = multiline; |
| 410 cached_bounds_and_offset_valid_ = false; | 434 cached_bounds_and_offset_valid_ = false; |
| 411 lines_.clear(); | 435 lines_.clear(); |
| 412 } | 436 } |
| 413 } | 437 } |
| 414 | 438 |
| 415 void RenderText::SetDisplayRect(const Rect& r) { | 439 void RenderText::SetDisplayRect(const Rect& r) { |
| 416 display_rect_ = r; | 440 display_rect_ = r; |
| 441 baseline_ = kInvalidBaseline; | |
| 417 cached_bounds_and_offset_valid_ = false; | 442 cached_bounds_and_offset_valid_ = false; |
| 418 lines_.clear(); | 443 lines_.clear(); |
| 419 } | 444 } |
| 420 | 445 |
| 421 void RenderText::SetCursorPosition(size_t position) { | 446 void RenderText::SetCursorPosition(size_t position) { |
| 422 MoveCursorTo(position, false); | 447 MoveCursorTo(position, false); |
| 423 } | 448 } |
| 424 | 449 |
| 425 void RenderText::MoveCursor(BreakType break_type, | 450 void RenderText::MoveCursor(BreakType break_type, |
| 426 VisualCursorDirection direction, | 451 VisualCursorDirection direction, |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 646 | 671 |
| 647 SizeF RenderText::GetStringSizeF() { | 672 SizeF RenderText::GetStringSizeF() { |
| 648 const Size size = GetStringSize(); | 673 const Size size = GetStringSize(); |
| 649 return SizeF(size.width(), size.height()); | 674 return SizeF(size.width(), size.height()); |
| 650 } | 675 } |
| 651 | 676 |
| 652 int RenderText::GetContentWidth() { | 677 int RenderText::GetContentWidth() { |
| 653 return GetStringSize().width() + (cursor_enabled_ ? 1 : 0); | 678 return GetStringSize().width() + (cursor_enabled_ ? 1 : 0); |
| 654 } | 679 } |
| 655 | 680 |
| 681 int RenderText::GetBaseline() { | |
| 682 if (baseline_ == kInvalidBaseline) | |
| 683 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list()); | |
|
Alexei Svitkine (slow)
2013/10/24 15:03:55
Nit: Add DCHECK_NE(kInvalidBaseline, baseline_);
Yuki
2013/10/24 15:17:36
Done.
| |
| 684 return baseline_; | |
| 685 } | |
| 686 | |
| 656 void RenderText::Draw(Canvas* canvas) { | 687 void RenderText::Draw(Canvas* canvas) { |
| 657 EnsureLayout(); | 688 EnsureLayout(); |
| 658 | 689 |
| 659 if (clip_to_display_rect()) { | 690 if (clip_to_display_rect()) { |
| 660 Rect clip_rect(display_rect()); | 691 Rect clip_rect(display_rect()); |
| 661 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); | 692 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); |
| 662 | 693 |
| 663 canvas->Save(); | 694 canvas->Save(); |
| 664 canvas->ClipRect(clip_rect); | 695 canvas->ClipRect(clip_rect); |
| 665 } | 696 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 777 return SelectionModel(sel.start(), | 808 return SelectionModel(sel.start(), |
| 778 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); | 809 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); |
| 779 } | 810 } |
| 780 | 811 |
| 781 void RenderText::SetTextShadows(const ShadowValues& shadows) { | 812 void RenderText::SetTextShadows(const ShadowValues& shadows) { |
| 782 text_shadows_ = shadows; | 813 text_shadows_ = shadows; |
| 783 } | 814 } |
| 784 | 815 |
| 785 RenderText::RenderText() | 816 RenderText::RenderText() |
| 786 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), | 817 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), |
| 787 vertical_alignment_(ALIGN_VCENTER), | |
| 788 directionality_mode_(DIRECTIONALITY_FROM_TEXT), | 818 directionality_mode_(DIRECTIONALITY_FROM_TEXT), |
| 789 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 819 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
| 790 cursor_enabled_(true), | 820 cursor_enabled_(true), |
| 791 cursor_visible_(false), | 821 cursor_visible_(false), |
| 792 insert_mode_(true), | 822 insert_mode_(true), |
| 793 cursor_color_(kDefaultColor), | 823 cursor_color_(kDefaultColor), |
| 794 selection_color_(kDefaultColor), | 824 selection_color_(kDefaultColor), |
| 795 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 825 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 796 focused_(false), | 826 focused_(false), |
| 797 composition_range_(Range::InvalidRange()), | 827 composition_range_(Range::InvalidRange()), |
| 798 colors_(kDefaultColor), | 828 colors_(kDefaultColor), |
| 799 styles_(NUM_TEXT_STYLES), | 829 styles_(NUM_TEXT_STYLES), |
| 800 composition_and_selection_styles_applied_(false), | 830 composition_and_selection_styles_applied_(false), |
| 801 obscured_(false), | 831 obscured_(false), |
| 802 obscured_reveal_index_(-1), | 832 obscured_reveal_index_(-1), |
| 803 truncate_length_(0), | 833 truncate_length_(0), |
| 804 multiline_(false), | 834 multiline_(false), |
| 805 fade_head_(false), | 835 fade_head_(false), |
| 806 fade_tail_(false), | 836 fade_tail_(false), |
| 807 background_is_transparent_(false), | 837 background_is_transparent_(false), |
| 808 clip_to_display_rect_(true), | 838 clip_to_display_rect_(true), |
| 839 baseline_(kInvalidBaseline), | |
| 809 cached_bounds_and_offset_valid_(false) { | 840 cached_bounds_and_offset_valid_(false) { |
| 810 } | 841 } |
| 811 | 842 |
| 812 const Vector2d& RenderText::GetUpdatedDisplayOffset() { | 843 const Vector2d& RenderText::GetUpdatedDisplayOffset() { |
| 813 UpdateCachedBoundsAndOffset(); | 844 UpdateCachedBoundsAndOffset(); |
| 814 return display_offset_; | 845 return display_offset_; |
| 815 } | 846 } |
| 816 | 847 |
| 817 SelectionModel RenderText::GetAdjacentSelectionModel( | 848 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 818 const SelectionModel& current, | 849 const SelectionModel& current, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 #if defined(OS_WIN) | 993 #if defined(OS_WIN) |
| 963 const int width = lines_[line_number].size.width() + | 994 const int width = lines_[line_number].size.width() + |
| 964 (cursor_enabled_ ? 1 : 0); | 995 (cursor_enabled_ ? 1 : 0); |
| 965 #else | 996 #else |
| 966 const int width = GetContentWidth(); | 997 const int width = GetContentWidth(); |
| 967 #endif | 998 #endif |
| 968 offset.set_x(display_rect().width() - width); | 999 offset.set_x(display_rect().width() - width); |
| 969 if (horizontal_alignment_ == ALIGN_CENTER) | 1000 if (horizontal_alignment_ == ALIGN_CENTER) |
| 970 offset.set_x(offset.x() / 2); | 1001 offset.set_x(offset.x() / 2); |
| 971 } | 1002 } |
| 972 if (vertical_alignment_ != ALIGN_TOP) { | 1003 offset.set_y(GetBaseline() - GetLayoutTextBaseline()); |
| 973 offset.set_y(display_rect().height() - GetStringSize().height()); | |
| 974 if (vertical_alignment_ == ALIGN_VCENTER) | |
| 975 offset.set_y(offset.y() / 2); | |
| 976 } | |
| 977 return offset; | 1004 return offset; |
| 978 } | 1005 } |
| 979 | 1006 |
| 980 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { | 1007 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { |
| 981 if (multiline() || (!fade_head() && !fade_tail())) | 1008 if (multiline() || (!fade_head() && !fade_tail())) |
| 982 return; | 1009 return; |
| 983 | 1010 |
| 984 const int display_width = display_rect().width(); | 1011 const int display_width = display_rect().width(); |
| 985 | 1012 |
| 986 // If the text fits as-is, no need to fade. | 1013 // If the text fits as-is, no need to fade. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 cursor_bounds_ += delta_offset; | 1159 cursor_bounds_ += delta_offset; |
| 1133 } | 1160 } |
| 1134 | 1161 |
| 1135 void RenderText::DrawSelection(Canvas* canvas) { | 1162 void RenderText::DrawSelection(Canvas* canvas) { |
| 1136 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1163 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
| 1137 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1164 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
| 1138 canvas->FillRect(*i, selection_background_focused_color_); | 1165 canvas->FillRect(*i, selection_background_focused_color_); |
| 1139 } | 1166 } |
| 1140 | 1167 |
| 1141 } // namespace gfx | 1168 } // namespace gfx |
| OLD | NEW |