| 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 const int min_shift = std::min(0, display_height - font_height); |
| 61 const int max_shift = std::abs(display_height - font_height); |
| 62 const int baseline = font_list.GetBaseline(); |
| 63 const int cap_height = font_list.GetCapHeight(); |
| 64 const int internal_leading = baseline - cap_height; |
| 65 const int baseline_shift = |
| 66 (display_height - cap_height) / 2 - internal_leading; |
| 67 return baseline + std::max(min_shift, std::min(max_shift, baseline_shift)); |
| 68 } |
| 69 |
| 47 // Converts |gfx::Font::FontStyle| flags to |SkTypeface::Style| flags. | 70 // Converts |gfx::Font::FontStyle| flags to |SkTypeface::Style| flags. |
| 48 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { | 71 SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) { |
| 49 int skia_style = SkTypeface::kNormal; | 72 int skia_style = SkTypeface::kNormal; |
| 50 skia_style |= (font_style & gfx::Font::BOLD) ? SkTypeface::kBold : 0; | 73 skia_style |= (font_style & gfx::Font::BOLD) ? SkTypeface::kBold : 0; |
| 51 skia_style |= (font_style & gfx::Font::ITALIC) ? SkTypeface::kItalic : 0; | 74 skia_style |= (font_style & gfx::Font::ITALIC) ? SkTypeface::kItalic : 0; |
| 52 return static_cast<SkTypeface::Style>(skia_style); | 75 return static_cast<SkTypeface::Style>(skia_style); |
| 53 } | 76 } |
| 54 | 77 |
| 55 // Given |font| and |display_width|, returns the width of the fade gradient. | 78 // Given |font| and |display_width|, returns the width of the fade gradient. |
| 56 int CalculateFadeGradientWidth(const Font& font, int display_width) { | 79 int CalculateFadeGradientWidth(const Font& font, int display_width) { |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 } | 364 } |
| 342 | 365 |
| 343 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { | 366 void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { |
| 344 if (horizontal_alignment_ != alignment) { | 367 if (horizontal_alignment_ != alignment) { |
| 345 horizontal_alignment_ = alignment; | 368 horizontal_alignment_ = alignment; |
| 346 display_offset_ = Vector2d(); | 369 display_offset_ = Vector2d(); |
| 347 cached_bounds_and_offset_valid_ = false; | 370 cached_bounds_and_offset_valid_ = false; |
| 348 } | 371 } |
| 349 } | 372 } |
| 350 | 373 |
| 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) { | 374 void RenderText::SetFontList(const FontList& font_list) { |
| 360 font_list_ = font_list; | 375 font_list_ = font_list; |
| 376 baseline_ = kInvalidBaseline; |
| 361 cached_bounds_and_offset_valid_ = false; | 377 cached_bounds_and_offset_valid_ = false; |
| 362 ResetLayout(); | 378 ResetLayout(); |
| 363 } | 379 } |
| 364 | 380 |
| 365 void RenderText::SetFont(const Font& font) { | 381 void RenderText::SetFont(const Font& font) { |
| 366 SetFontList(FontList(font)); | 382 SetFontList(FontList(font)); |
| 367 } | 383 } |
| 368 | 384 |
| 369 void RenderText::SetFontSize(int size) { | 385 void RenderText::SetFontSize(int size) { |
| 370 SetFontList(font_list_.DeriveFontListWithSize(size)); | 386 SetFontList(font_list_.DeriveFontListWithSize(size)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 void RenderText::SetMultiline(bool multiline) { | 423 void RenderText::SetMultiline(bool multiline) { |
| 408 if (multiline != multiline_) { | 424 if (multiline != multiline_) { |
| 409 multiline_ = multiline; | 425 multiline_ = multiline; |
| 410 cached_bounds_and_offset_valid_ = false; | 426 cached_bounds_and_offset_valid_ = false; |
| 411 lines_.clear(); | 427 lines_.clear(); |
| 412 } | 428 } |
| 413 } | 429 } |
| 414 | 430 |
| 415 void RenderText::SetDisplayRect(const Rect& r) { | 431 void RenderText::SetDisplayRect(const Rect& r) { |
| 416 display_rect_ = r; | 432 display_rect_ = r; |
| 433 baseline_ = kInvalidBaseline; |
| 417 cached_bounds_and_offset_valid_ = false; | 434 cached_bounds_and_offset_valid_ = false; |
| 418 lines_.clear(); | 435 lines_.clear(); |
| 419 } | 436 } |
| 420 | 437 |
| 421 void RenderText::SetCursorPosition(size_t position) { | 438 void RenderText::SetCursorPosition(size_t position) { |
| 422 MoveCursorTo(position, false); | 439 MoveCursorTo(position, false); |
| 423 } | 440 } |
| 424 | 441 |
| 425 void RenderText::MoveCursor(BreakType break_type, | 442 void RenderText::MoveCursor(BreakType break_type, |
| 426 VisualCursorDirection direction, | 443 VisualCursorDirection direction, |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 | 663 |
| 647 SizeF RenderText::GetStringSizeF() { | 664 SizeF RenderText::GetStringSizeF() { |
| 648 const Size size = GetStringSize(); | 665 const Size size = GetStringSize(); |
| 649 return SizeF(size.width(), size.height()); | 666 return SizeF(size.width(), size.height()); |
| 650 } | 667 } |
| 651 | 668 |
| 652 int RenderText::GetContentWidth() { | 669 int RenderText::GetContentWidth() { |
| 653 return GetStringSize().width() + (cursor_enabled_ ? 1 : 0); | 670 return GetStringSize().width() + (cursor_enabled_ ? 1 : 0); |
| 654 } | 671 } |
| 655 | 672 |
| 673 int RenderText::GetBaseline() { |
| 674 if (baseline_ == kInvalidBaseline) |
| 675 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list()); |
| 676 DCHECK_NE(kInvalidBaseline, baseline_); |
| 677 return baseline_; |
| 678 } |
| 679 |
| 656 void RenderText::Draw(Canvas* canvas) { | 680 void RenderText::Draw(Canvas* canvas) { |
| 657 EnsureLayout(); | 681 EnsureLayout(); |
| 658 | 682 |
| 659 if (clip_to_display_rect()) { | 683 if (clip_to_display_rect()) { |
| 660 Rect clip_rect(display_rect()); | 684 Rect clip_rect(display_rect()); |
| 661 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); | 685 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); |
| 662 | 686 |
| 663 canvas->Save(); | 687 canvas->Save(); |
| 664 canvas->ClipRect(clip_rect); | 688 canvas->ClipRect(clip_rect); |
| 665 } | 689 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 return SelectionModel(sel.start(), | 801 return SelectionModel(sel.start(), |
| 778 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); | 802 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); |
| 779 } | 803 } |
| 780 | 804 |
| 781 void RenderText::SetTextShadows(const ShadowValues& shadows) { | 805 void RenderText::SetTextShadows(const ShadowValues& shadows) { |
| 782 text_shadows_ = shadows; | 806 text_shadows_ = shadows; |
| 783 } | 807 } |
| 784 | 808 |
| 785 RenderText::RenderText() | 809 RenderText::RenderText() |
| 786 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), | 810 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), |
| 787 vertical_alignment_(ALIGN_VCENTER), | |
| 788 directionality_mode_(DIRECTIONALITY_FROM_TEXT), | 811 directionality_mode_(DIRECTIONALITY_FROM_TEXT), |
| 789 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 812 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
| 790 cursor_enabled_(true), | 813 cursor_enabled_(true), |
| 791 cursor_visible_(false), | 814 cursor_visible_(false), |
| 792 insert_mode_(true), | 815 insert_mode_(true), |
| 793 cursor_color_(kDefaultColor), | 816 cursor_color_(kDefaultColor), |
| 794 selection_color_(kDefaultColor), | 817 selection_color_(kDefaultColor), |
| 795 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 818 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 796 focused_(false), | 819 focused_(false), |
| 797 composition_range_(Range::InvalidRange()), | 820 composition_range_(Range::InvalidRange()), |
| 798 colors_(kDefaultColor), | 821 colors_(kDefaultColor), |
| 799 styles_(NUM_TEXT_STYLES), | 822 styles_(NUM_TEXT_STYLES), |
| 800 composition_and_selection_styles_applied_(false), | 823 composition_and_selection_styles_applied_(false), |
| 801 obscured_(false), | 824 obscured_(false), |
| 802 obscured_reveal_index_(-1), | 825 obscured_reveal_index_(-1), |
| 803 truncate_length_(0), | 826 truncate_length_(0), |
| 804 multiline_(false), | 827 multiline_(false), |
| 805 fade_head_(false), | 828 fade_head_(false), |
| 806 fade_tail_(false), | 829 fade_tail_(false), |
| 807 background_is_transparent_(false), | 830 background_is_transparent_(false), |
| 808 clip_to_display_rect_(true), | 831 clip_to_display_rect_(true), |
| 832 baseline_(kInvalidBaseline), |
| 809 cached_bounds_and_offset_valid_(false) { | 833 cached_bounds_and_offset_valid_(false) { |
| 810 } | 834 } |
| 811 | 835 |
| 812 const Vector2d& RenderText::GetUpdatedDisplayOffset() { | 836 const Vector2d& RenderText::GetUpdatedDisplayOffset() { |
| 813 UpdateCachedBoundsAndOffset(); | 837 UpdateCachedBoundsAndOffset(); |
| 814 return display_offset_; | 838 return display_offset_; |
| 815 } | 839 } |
| 816 | 840 |
| 817 SelectionModel RenderText::GetAdjacentSelectionModel( | 841 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 818 const SelectionModel& current, | 842 const SelectionModel& current, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 #if defined(OS_WIN) | 986 #if defined(OS_WIN) |
| 963 const int width = lines_[line_number].size.width() + | 987 const int width = lines_[line_number].size.width() + |
| 964 (cursor_enabled_ ? 1 : 0); | 988 (cursor_enabled_ ? 1 : 0); |
| 965 #else | 989 #else |
| 966 const int width = GetContentWidth(); | 990 const int width = GetContentWidth(); |
| 967 #endif | 991 #endif |
| 968 offset.set_x(display_rect().width() - width); | 992 offset.set_x(display_rect().width() - width); |
| 969 if (horizontal_alignment_ == ALIGN_CENTER) | 993 if (horizontal_alignment_ == ALIGN_CENTER) |
| 970 offset.set_x(offset.x() / 2); | 994 offset.set_x(offset.x() / 2); |
| 971 } | 995 } |
| 972 if (vertical_alignment_ != ALIGN_TOP) { | 996 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; | 997 return offset; |
| 978 } | 998 } |
| 979 | 999 |
| 980 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { | 1000 void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { |
| 981 if (multiline() || (!fade_head() && !fade_tail())) | 1001 if (multiline() || (!fade_head() && !fade_tail())) |
| 982 return; | 1002 return; |
| 983 | 1003 |
| 984 const int display_width = display_rect().width(); | 1004 const int display_width = display_rect().width(); |
| 985 | 1005 |
| 986 // If the text fits as-is, no need to fade. | 1006 // 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; | 1152 cursor_bounds_ += delta_offset; |
| 1133 } | 1153 } |
| 1134 | 1154 |
| 1135 void RenderText::DrawSelection(Canvas* canvas) { | 1155 void RenderText::DrawSelection(Canvas* canvas) { |
| 1136 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1156 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
| 1137 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1157 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
| 1138 canvas->FillRect(*i, selection_background_focused_color_); | 1158 canvas->FillRect(*i, selection_background_focused_color_); |
| 1139 } | 1159 } |
| 1140 | 1160 |
| 1141 } // namespace gfx | 1161 } // namespace gfx |
| OLD | NEW |