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 |