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 |