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 | 8 |
9 #include "base/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 Rect clip_rect(display_rect()); | 604 Rect clip_rect(display_rect()); |
605 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); | 605 clip_rect.Inset(ShadowValue::GetMargin(text_shadows_)); |
606 | 606 |
607 canvas->Save(); | 607 canvas->Save(); |
608 canvas->ClipRect(clip_rect); | 608 canvas->ClipRect(clip_rect); |
609 } | 609 } |
610 | 610 |
611 if (!text().empty()) | 611 if (!text().empty()) |
612 DrawSelection(canvas); | 612 DrawSelection(canvas); |
613 | 613 |
614 DrawCursor(canvas); | 614 if (cursor_enabled() && cursor_visible() && focused()) |
| 615 DrawCursor(canvas, selection_model_); |
615 | 616 |
616 if (!text().empty()) | 617 if (!text().empty()) |
617 DrawVisualText(canvas); | 618 DrawVisualText(canvas); |
618 | 619 |
619 if (clip_to_display_rect()) | 620 if (clip_to_display_rect()) |
620 canvas->Restore(); | 621 canvas->Restore(); |
621 } | 622 } |
622 | 623 |
| 624 void RenderText::DrawCursor(Canvas* canvas, const SelectionModel& position) { |
| 625 // Paint cursor. Replace cursor is drawn as rectangle for now. |
| 626 // TODO(msw): Draw a better cursor with a better indication of association. |
| 627 canvas->FillRect(GetCursorBounds(position, true), cursor_color_); |
| 628 } |
| 629 |
623 void RenderText::DrawSelectedText(Canvas* canvas) { | 630 void RenderText::DrawSelectedText(Canvas* canvas) { |
624 EnsureLayout(); | 631 EnsureLayout(); |
625 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 632 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
626 for (size_t i = 0; i < sel.size(); ++i) { | 633 for (size_t i = 0; i < sel.size(); ++i) { |
627 canvas->Save(); | 634 canvas->Save(); |
628 canvas->ClipRect(sel[i]); | 635 canvas->ClipRect(sel[i]); |
629 DrawVisualText(canvas); | 636 DrawVisualText(canvas); |
630 canvas->Restore(); | 637 canvas->Restore(); |
631 } | 638 } |
632 } | 639 } |
633 | 640 |
634 Rect RenderText::GetCursorBounds(const SelectionModel& caret, | 641 Rect RenderText::GetCursorBounds(const SelectionModel& caret, |
635 bool insert_mode) { | 642 bool insert_mode) { |
636 EnsureLayout(); | 643 EnsureLayout(); |
637 | 644 |
638 size_t caret_pos = caret.caret_pos(); | 645 size_t caret_pos = caret.caret_pos(); |
| 646 DCHECK(IsCursorablePosition(caret_pos)); |
639 // In overtype mode, ignore the affinity and always indicate that we will | 647 // In overtype mode, ignore the affinity and always indicate that we will |
640 // overtype the next character. | 648 // overtype the next character. |
641 LogicalCursorDirection caret_affinity = | 649 LogicalCursorDirection caret_affinity = |
642 insert_mode ? caret.caret_affinity() : CURSOR_FORWARD; | 650 insert_mode ? caret.caret_affinity() : CURSOR_FORWARD; |
643 int x = 0, width = 1, height = 0; | 651 int x = 0, width = 1, height = 0; |
644 if (caret_pos == (caret_affinity == CURSOR_BACKWARD ? 0 : text().length())) { | 652 if (caret_pos == (caret_affinity == CURSOR_BACKWARD ? 0 : text().length())) { |
645 // The caret is attached to the boundary. Always return a 1-dip width caret, | 653 // The caret is attached to the boundary. Always return a 1-dip width caret, |
646 // since there is nothing to overtype. | 654 // since there is nothing to overtype. |
647 Size size = GetStringSize(); | 655 Size size = GetStringSize(); |
648 if ((GetTextDirection() == base::i18n::RIGHT_TO_LEFT) == (caret_pos == 0)) | 656 if ((GetTextDirection() == base::i18n::RIGHT_TO_LEFT) == (caret_pos == 0)) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 if (sel.is_empty()) | 707 if (sel.is_empty()) |
700 return selection_model_; | 708 return selection_model_; |
701 return SelectionModel(sel.start(), | 709 return SelectionModel(sel.start(), |
702 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); | 710 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); |
703 } | 711 } |
704 | 712 |
705 void RenderText::SetTextShadows(const ShadowValues& shadows) { | 713 void RenderText::SetTextShadows(const ShadowValues& shadows) { |
706 text_shadows_ = shadows; | 714 text_shadows_ = shadows; |
707 } | 715 } |
708 | 716 |
| 717 // static |
| 718 bool RenderText::RangeContainsCaret(const ui::Range& range, |
| 719 size_t caret_pos, |
| 720 LogicalCursorDirection caret_affinity) { |
| 721 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). |
| 722 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? |
| 723 caret_pos - 1 : caret_pos + 1; |
| 724 return range.Contains(ui::Range(caret_pos, adjacent)); |
| 725 } |
| 726 |
709 RenderText::RenderText() | 727 RenderText::RenderText() |
710 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), | 728 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), |
711 directionality_mode_(DIRECTIONALITY_FROM_TEXT), | 729 directionality_mode_(DIRECTIONALITY_FROM_TEXT), |
712 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 730 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
713 cursor_enabled_(true), | 731 cursor_enabled_(true), |
714 cursor_visible_(false), | 732 cursor_visible_(false), |
715 insert_mode_(true), | 733 insert_mode_(true), |
716 cursor_color_(kDefaultColor), | 734 cursor_color_(kDefaultColor), |
717 selection_color_(kDefaultColor), | 735 selection_color_(kDefaultColor), |
718 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 736 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 text_rect, left_part, right_part, colors_.breaks().front().second); | 891 text_rect, left_part, right_part, colors_.breaks().front().second); |
874 if (shader) | 892 if (shader) |
875 renderer->SetShader(shader.get(), display_rect()); | 893 renderer->SetShader(shader.get(), display_rect()); |
876 } | 894 } |
877 | 895 |
878 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { | 896 void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) { |
879 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_); | 897 skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(text_shadows_); |
880 renderer->SetDrawLooper(looper.get()); | 898 renderer->SetDrawLooper(looper.get()); |
881 } | 899 } |
882 | 900 |
883 // static | |
884 bool RenderText::RangeContainsCaret(const ui::Range& range, | |
885 size_t caret_pos, | |
886 LogicalCursorDirection caret_affinity) { | |
887 // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). | |
888 size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? | |
889 caret_pos - 1 : caret_pos + 1; | |
890 return range.Contains(ui::Range(caret_pos, adjacent)); | |
891 } | |
892 | |
893 void RenderText::MoveCursorTo(size_t position, bool select) { | 901 void RenderText::MoveCursorTo(size_t position, bool select) { |
894 size_t cursor = std::min(position, text().length()); | 902 size_t cursor = std::min(position, text().length()); |
895 if (IsCursorablePosition(cursor)) | 903 if (IsCursorablePosition(cursor)) |
896 SetSelectionModel(SelectionModel( | 904 SetSelectionModel(SelectionModel( |
897 ui::Range(select ? selection().start() : cursor, cursor), | 905 ui::Range(select ? selection().start() : cursor, cursor), |
898 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); | 906 (cursor == 0) ? CURSOR_FORWARD : CURSOR_BACKWARD)); |
899 } | 907 } |
900 | 908 |
901 void RenderText::UpdateObscuredText() { | 909 void RenderText::UpdateObscuredText() { |
902 if (!obscured_) | 910 if (!obscured_) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 } | 964 } |
957 | 965 |
958 void RenderText::DrawSelection(Canvas* canvas) { | 966 void RenderText::DrawSelection(Canvas* canvas) { |
959 const SkColor color = focused() ? selection_background_focused_color_ : | 967 const SkColor color = focused() ? selection_background_focused_color_ : |
960 selection_background_unfocused_color_; | 968 selection_background_unfocused_color_; |
961 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 969 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
962 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 970 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
963 canvas->FillRect(*i, color); | 971 canvas->FillRect(*i, color); |
964 } | 972 } |
965 | 973 |
966 void RenderText::DrawCursor(Canvas* canvas) { | |
967 // Paint cursor. Replace cursor is drawn as rectangle for now. | |
968 // TODO(msw): Draw a better cursor with a better indication of association. | |
969 if (cursor_enabled() && cursor_visible() && focused()) { | |
970 canvas->FillRect(GetUpdatedCursorBounds(), | |
971 insert_mode_ ? cursor_color_ : selection_background_unfocused_color_); | |
972 } | |
973 } | |
974 | |
975 } // namespace gfx | 974 } // namespace gfx |
OLD | NEW |