Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: ui/gfx/render_text_unittest.cc

Issue 2541313002: RenderTextHarfBuzz: Add support for multi line text selection. (Closed)
Patch Set: --- Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <limits.h> 7 #include <limits.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 GetRenderTextHarfBuzz()->set_glyph_width_for_test(test_width); 507 GetRenderTextHarfBuzz()->set_glyph_width_for_test(test_width);
508 } 508 }
509 509
510 bool ShapeRunWithFont(const base::string16& text, 510 bool ShapeRunWithFont(const base::string16& text,
511 const Font& font, 511 const Font& font,
512 const FontRenderParams& params, 512 const FontRenderParams& params,
513 internal::TextRunHarfBuzz* run) { 513 internal::TextRunHarfBuzz* run) {
514 return GetRenderTextHarfBuzz()->ShapeRunWithFont(text, font, params, run); 514 return GetRenderTextHarfBuzz()->ShapeRunWithFont(text, font, params, run);
515 } 515 }
516 516
517 int GetCursorYForTesting(int line_num = 0) {
msw 2016/12/07 20:20:35 nit: use the line_num param in new tests, or remov
karandeepb 2016/12/12 10:36:19 Added tests using this.
518 test_api()->EnsureLayout();
519 const internal::Line& line = test_api()->lines()[line_num];
520 return GetRenderText()->GetLineOffset(line_num).y() +
521 line.size.height() / 2;
msw 2016/12/07 20:20:35 optional nit: just add 1 instead of half the line
karandeepb 2016/12/12 10:36:19 Done.
522 }
523
517 private: 524 private:
518 DISALLOW_COPY_AND_ASSIGN(RenderTextHarfBuzzTest); 525 DISALLOW_COPY_AND_ASSIGN(RenderTextHarfBuzzTest);
519 }; 526 };
520 527
521 #if defined(OS_MACOSX) 528 #if defined(OS_MACOSX)
522 // Test fixture class. Use for tests which are only to be run for RenderTextMac. 529 // Test fixture class. Use for tests which are only to be run for RenderTextMac.
523 class RenderTextMacTest : public RenderTextTest { 530 class RenderTextMacTest : public RenderTextTest {
524 public: 531 public:
525 RenderTextMacTest() {} 532 RenderTextMacTest() {}
526 533
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(1U)); 788 EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(1U));
782 EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(2U)); 789 EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(2U));
783 EXPECT_EQ(0U, test_api()->DisplayIndexToTextIndex(0U)); 790 EXPECT_EQ(0U, test_api()->DisplayIndexToTextIndex(0U));
784 EXPECT_EQ(2U, test_api()->DisplayIndexToTextIndex(1U)); 791 EXPECT_EQ(2U, test_api()->DisplayIndexToTextIndex(1U));
785 EXPECT_TRUE(render_text->IsValidCursorIndex(0U)); 792 EXPECT_TRUE(render_text->IsValidCursorIndex(0U));
786 EXPECT_FALSE(render_text->IsValidCursorIndex(1U)); 793 EXPECT_FALSE(render_text->IsValidCursorIndex(1U));
787 EXPECT_TRUE(render_text->IsValidCursorIndex(2U)); 794 EXPECT_TRUE(render_text->IsValidCursorIndex(2U));
788 795
789 // FindCursorPosition() should not return positions between a surrogate pair. 796 // FindCursorPosition() should not return positions between a surrogate pair.
790 render_text->SetDisplayRect(Rect(0, 0, 20, 20)); 797 render_text->SetDisplayRect(Rect(0, 0, 20, 20));
791 EXPECT_EQ(render_text->FindCursorPosition(Point(0, 0)).caret_pos(), 0U); 798 const int cursor_y = GetCursorYForTesting();
792 EXPECT_EQ(render_text->FindCursorPosition(Point(20, 0)).caret_pos(), 2U); 799 EXPECT_EQ(render_text->FindCursorPosition(Point(0, cursor_y)).caret_pos(),
800 0U);
801 EXPECT_EQ(render_text->FindCursorPosition(Point(20, cursor_y)).caret_pos(),
802 2U);
793 for (int x = -1; x <= 20; ++x) { 803 for (int x = -1; x <= 20; ++x) {
794 SelectionModel selection = render_text->FindCursorPosition(Point(x, 0)); 804 SelectionModel selection =
805 render_text->FindCursorPosition(Point(x, cursor_y));
795 EXPECT_TRUE(selection.caret_pos() == 0U || selection.caret_pos() == 2U); 806 EXPECT_TRUE(selection.caret_pos() == 0U || selection.caret_pos() == 2U);
796 } 807 }
797 808
798 // GetGlyphBounds() should yield the entire string bounds for text index 0. 809 // GetGlyphBounds() should yield the entire string bounds for text index 0.
799 EXPECT_EQ(render_text->GetStringSize().width(), 810 EXPECT_EQ(render_text->GetStringSize().width(),
800 static_cast<int>(render_text->GetGlyphBounds(0U).length())); 811 static_cast<int>(render_text->GetGlyphBounds(0U).length()));
801 812
802 // Cursoring is independent of underlying characters when text is obscured. 813 // Cursoring is independent of underlying characters when text is obscured.
803 const wchar_t* const texts[] = { 814 const wchar_t* const texts[] = {
804 kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl, 815 kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 const wchar_t* kTestStrings[] = { kLtrRtl, kLtrRtlLtr, kRtlLtr, kRtlLtrRtl }; 1787 const wchar_t* kTestStrings[] = { kLtrRtl, kLtrRtlLtr, kRtlLtr, kRtlLtrRtl };
1777 RenderText* render_text = GetRenderText(); 1788 RenderText* render_text = GetRenderText();
1778 render_text->SetDisplayRect(Rect(0, 0, 100, 20)); 1789 render_text->SetDisplayRect(Rect(0, 0, 100, 20));
1779 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 1790 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1780 SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i)); 1791 SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i));
1781 render_text->SetText(WideToUTF16(kTestStrings[i])); 1792 render_text->SetText(WideToUTF16(kTestStrings[i]));
1782 for (size_t j = 0; j < render_text->text().length(); ++j) { 1793 for (size_t j = 0; j < render_text->text().length(); ++j) {
1783 const Range range(render_text->GetGlyphBounds(j)); 1794 const Range range(render_text->GetGlyphBounds(j));
1784 // Test a point just inside the leading edge of the glyph bounds. 1795 // Test a point just inside the leading edge of the glyph bounds.
1785 int x = range.is_reversed() ? range.GetMax() - 1 : range.GetMin() + 1; 1796 int x = range.is_reversed() ? range.GetMax() - 1 : range.GetMin() + 1;
1786 EXPECT_EQ(j, render_text->FindCursorPosition(Point(x, 0)).caret_pos()); 1797 EXPECT_EQ(
1798 j, render_text->FindCursorPosition(Point(x, GetCursorYForTesting()))
1799 .caret_pos());
1787 } 1800 }
1788 } 1801 }
1789 } 1802 }
1790 1803
1791 TEST_P(RenderTextTest, EdgeSelectionModels) { 1804 TEST_P(RenderTextTest, EdgeSelectionModels) {
1792 // Simple Latin text. 1805 // Simple Latin text.
1793 const base::string16 kLatin = WideToUTF16(L"abc"); 1806 const base::string16 kLatin = WideToUTF16(L"abc");
1794 // LTR 2-character grapheme. 1807 // LTR 2-character grapheme.
1795 const base::string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f"); 1808 const base::string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f");
1796 // LTR 2-character grapheme, LTR a, LTR 2-character grapheme. 1809 // LTR 2-character grapheme, LTR a, LTR 2-character grapheme.
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
2856 } 2869 }
2857 } 2870 }
2858 2871
2859 TEST_P(RenderTextHarfBuzzTest, Multiline_Newline) { 2872 TEST_P(RenderTextHarfBuzzTest, Multiline_Newline) {
2860 const struct { 2873 const struct {
2861 const wchar_t* const text; 2874 const wchar_t* const text;
2862 const size_t lines_count; 2875 const size_t lines_count;
2863 // Ranges of the characters on each line preceding the newline. 2876 // Ranges of the characters on each line preceding the newline.
2864 const Range line_char_ranges[3]; 2877 const Range line_char_ranges[3];
2865 } kTestStrings[] = { 2878 } kTestStrings[] = {
2866 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } }, 2879 {L"abc\ndef", 2ul, {Range(0, 3), Range(4, 7), Range::InvalidRange()}},
2867 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 6), Range::InvalidRange() } }, 2880 {L"a \n b ", 2ul, {Range(0, 2), Range(3, 6), Range::InvalidRange()}},
2868 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } }, 2881 {L"ab\n", 2ul, {Range(0, 2), Range(), Range::InvalidRange()}},
2869 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } }, 2882 {L"a\n\nb", 3ul, {Range(0, 1), Range(2, 3), Range(3, 4)}},
2870 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } }, 2883 {L"\nab", 2ul, {Range(0, 1), Range(1, 3), Range::InvalidRange()}},
2871 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } }, 2884 {L"\n", 2ul, {Range(0, 1), Range(), Range::InvalidRange()}},
2872 }; 2885 };
2873 2886
2874 RenderText* render_text = GetRenderText(); 2887 RenderText* render_text = GetRenderText();
2875 render_text->SetDisplayRect(Rect(200, 1000)); 2888 render_text->SetDisplayRect(Rect(200, 1000));
2876 render_text->SetMultiline(true); 2889 render_text->SetMultiline(true);
2877 2890
2878 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2891 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2879 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 2892 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2880 render_text->SetText(WideToUTF16(kTestStrings[i].text)); 2893 render_text->SetText(WideToUTF16(kTestStrings[i].text));
2881 render_text->Draw(canvas()); 2894 render_text->Draw(canvas());
(...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after
3891 const int kWordTwoStartIndex = 6; 3904 const int kWordTwoStartIndex = 6;
3892 3905
3893 RenderText* render_text = GetRenderText(); 3906 RenderText* render_text = GetRenderText();
3894 render_text->SetDisplayRect(Rect(100, 30)); 3907 render_text->SetDisplayRect(Rect(100, 30));
3895 render_text->SetText(ltr); 3908 render_text->SetText(ltr);
3896 render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(0, 3)); 3909 render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(0, 3));
3897 render_text->ApplyStyle(UNDERLINE, true, Range(1, 5)); 3910 render_text->ApplyStyle(UNDERLINE, true, Range(1, 5));
3898 render_text->ApplyStyle(ITALIC, true, Range(3, 8)); 3911 render_text->ApplyStyle(ITALIC, true, Range(3, 8));
3899 render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(5, 7)); 3912 render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(5, 7));
3900 render_text->ApplyStyle(STRIKE, true, Range(1, 7)); 3913 render_text->ApplyStyle(STRIKE, true, Range(1, 7));
3914 const int cursor_y = GetCursorYForTesting();
3901 3915
3902 const std::vector<RenderText::FontSpan> font_spans = 3916 const std::vector<RenderText::FontSpan> font_spans =
3903 render_text->GetFontSpansForTesting(); 3917 render_text->GetFontSpansForTesting();
3904 3918
3905 // Create expected decorated text instances. 3919 // Create expected decorated text instances.
3906 DecoratedText expected_word_1; 3920 DecoratedText expected_word_1;
3907 expected_word_1.text = ASCIIToUTF16("ab"); 3921 expected_word_1.text = ASCIIToUTF16("ab");
3908 // Attributes for the characters 'a' and 'b' at logical indices 2 and 3 3922 // Attributes for the characters 'a' and 'b' at logical indices 2 and 3
3909 // respectively. 3923 // respectively.
3910 expected_word_1.attributes.push_back(CreateRangedAttribute( 3924 expected_word_1.attributes.push_back(CreateRangedAttribute(
(...skipping 13 matching lines...) Expand all
3924 ITALIC_MASK | DIAGONAL_STRIKE_MASK | STRIKE_MASK)); 3938 ITALIC_MASK | DIAGONAL_STRIKE_MASK | STRIKE_MASK));
3925 const Rect left_glyph_word_2 = render_text->GetCursorBounds( 3939 const Rect left_glyph_word_2 = render_text->GetCursorBounds(
3926 SelectionModel(kWordTwoStartIndex, CURSOR_FORWARD), false); 3940 SelectionModel(kWordTwoStartIndex, CURSOR_FORWARD), false);
3927 3941
3928 DecoratedText decorated_word; 3942 DecoratedText decorated_word;
3929 Point baseline_point; 3943 Point baseline_point;
3930 3944
3931 { 3945 {
3932 SCOPED_TRACE(base::StringPrintf("Query to the left of text bounds")); 3946 SCOPED_TRACE(base::StringPrintf("Query to the left of text bounds"));
3933 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint( 3947 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint(
3934 Point(-5, 5), &decorated_word, &baseline_point)); 3948 Point(-5, cursor_y), &decorated_word, &baseline_point));
3935 VerifyDecoratedWordsAreEqual(expected_word_1, decorated_word); 3949 VerifyDecoratedWordsAreEqual(expected_word_1, decorated_word);
3936 EXPECT_TRUE(left_glyph_word_1.Contains(baseline_point)); 3950 EXPECT_TRUE(left_glyph_word_1.Contains(baseline_point));
3937 } 3951 }
3938 { 3952 {
3939 SCOPED_TRACE(base::StringPrintf("Query to the right of text bounds")); 3953 SCOPED_TRACE(base::StringPrintf("Query to the right of text bounds"));
3940 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint( 3954 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint(
3941 Point(105, 5), &decorated_word, &baseline_point)); 3955 Point(105, cursor_y), &decorated_word, &baseline_point));
3942 VerifyDecoratedWordsAreEqual(expected_word_2, decorated_word); 3956 VerifyDecoratedWordsAreEqual(expected_word_2, decorated_word);
3943 EXPECT_TRUE(left_glyph_word_2.Contains(baseline_point)); 3957 EXPECT_TRUE(left_glyph_word_2.Contains(baseline_point));
3944 } 3958 }
3945 3959
3946 for (size_t i = 0; i < render_text->text().length(); i++) { 3960 for (size_t i = 0; i < render_text->text().length(); i++) {
3947 SCOPED_TRACE(base::StringPrintf("Case[%" PRIuS "]", i)); 3961 SCOPED_TRACE(base::StringPrintf("Case[%" PRIuS "]", i));
3948 // Query the decorated word using the origin of the i'th glyph's bounds. 3962 // Query the decorated word using the origin of the i'th glyph's bounds.
3949 const Point query = 3963 const Point query =
3950 render_text->GetCursorBounds(SelectionModel(i, CURSOR_FORWARD), false) 3964 render_text->GetCursorBounds(SelectionModel(i, CURSOR_FORWARD), false)
3951 .origin(); 3965 .origin();
(...skipping 23 matching lines...) Expand all
3975 const int kWordTwoStartIndex = 5; 3989 const int kWordTwoStartIndex = 5;
3976 3990
3977 RenderText* render_text = GetRenderText(); 3991 RenderText* render_text = GetRenderText();
3978 render_text->SetDisplayRect(Rect(100, 30)); 3992 render_text->SetDisplayRect(Rect(100, 30));
3979 render_text->SetText(rtl); 3993 render_text->SetText(rtl);
3980 render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(2, 3)); 3994 render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(2, 3));
3981 render_text->ApplyStyle(UNDERLINE, true, Range(3, 6)); 3995 render_text->ApplyStyle(UNDERLINE, true, Range(3, 6));
3982 render_text->ApplyStyle(ITALIC, true, Range(0, 3)); 3996 render_text->ApplyStyle(ITALIC, true, Range(0, 3));
3983 render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(0, 2)); 3997 render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(0, 2));
3984 render_text->ApplyStyle(STRIKE, true, Range(2, 5)); 3998 render_text->ApplyStyle(STRIKE, true, Range(2, 5));
3999 const int cursor_y = GetCursorYForTesting();
3985 4000
3986 const std::vector<RenderText::FontSpan> font_spans = 4001 const std::vector<RenderText::FontSpan> font_spans =
3987 render_text->GetFontSpansForTesting(); 4002 render_text->GetFontSpansForTesting();
3988 4003
3989 // Create expected decorated text instance. 4004 // Create expected decorated text instance.
3990 DecoratedText expected_word_1; 4005 DecoratedText expected_word_1;
3991 expected_word_1.text = WideToUTF16(L"\x0634\x0632"); 4006 expected_word_1.text = WideToUTF16(L"\x0634\x0632");
3992 // Attributes for characters at logical indices 1 and 2. 4007 // Attributes for characters at logical indices 1 and 2.
3993 expected_word_1.attributes.push_back(CreateRangedAttribute( 4008 expected_word_1.attributes.push_back(CreateRangedAttribute(
3994 font_spans, 0, kWordOneStartIndex, Font::Weight::NORMAL, 4009 font_spans, 0, kWordOneStartIndex, Font::Weight::NORMAL,
(...skipping 12 matching lines...) Expand all
4007 font_spans, 0, kWordTwoStartIndex, Font::Weight::NORMAL, UNDERLINE_MASK)); 4022 font_spans, 0, kWordTwoStartIndex, Font::Weight::NORMAL, UNDERLINE_MASK));
4008 const Rect left_glyph_word_2 = render_text->GetCursorBounds( 4023 const Rect left_glyph_word_2 = render_text->GetCursorBounds(
4009 SelectionModel(kWordTwoStartIndex, CURSOR_FORWARD), false); 4024 SelectionModel(kWordTwoStartIndex, CURSOR_FORWARD), false);
4010 4025
4011 DecoratedText decorated_word; 4026 DecoratedText decorated_word;
4012 Point baseline_point; 4027 Point baseline_point;
4013 4028
4014 { 4029 {
4015 SCOPED_TRACE(base::StringPrintf("Query to the left of text bounds")); 4030 SCOPED_TRACE(base::StringPrintf("Query to the left of text bounds"));
4016 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint( 4031 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint(
4017 Point(-5, 5), &decorated_word, &baseline_point)); 4032 Point(-5, cursor_y), &decorated_word, &baseline_point));
4018 VerifyDecoratedWordsAreEqual(expected_word_2, decorated_word); 4033 VerifyDecoratedWordsAreEqual(expected_word_2, decorated_word);
4019 EXPECT_TRUE(left_glyph_word_2.Contains(baseline_point)); 4034 EXPECT_TRUE(left_glyph_word_2.Contains(baseline_point));
4020 } 4035 }
4021 { 4036 {
4022 SCOPED_TRACE(base::StringPrintf("Query to the right of text bounds")); 4037 SCOPED_TRACE(base::StringPrintf("Query to the right of text bounds"));
4023 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint( 4038 EXPECT_TRUE(render_text->GetDecoratedWordAtPoint(
4024 Point(105, 5), &decorated_word, &baseline_point)); 4039 Point(105, cursor_y), &decorated_word, &baseline_point));
4025 VerifyDecoratedWordsAreEqual(expected_word_1, decorated_word); 4040 VerifyDecoratedWordsAreEqual(expected_word_1, decorated_word);
4026 EXPECT_TRUE(left_glyph_word_1.Contains(baseline_point)); 4041 EXPECT_TRUE(left_glyph_word_1.Contains(baseline_point));
4027 } 4042 }
4028 4043
4029 for (size_t i = 0; i < render_text->text().length(); i++) { 4044 for (size_t i = 0; i < render_text->text().length(); i++) {
4030 SCOPED_TRACE(base::StringPrintf("Case[%" PRIuS "]", i)); 4045 SCOPED_TRACE(base::StringPrintf("Case[%" PRIuS "]", i));
4031 4046
4032 // Query the decorated word using the top right point of the i'th glyph's 4047 // Query the decorated word using the top right point of the i'th glyph's
4033 // bounds. 4048 // bounds.
4034 const Point query = 4049 const Point query =
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4094 ::testing::Values(RENDER_TEXT_HARFBUZZ), 4109 ::testing::Values(RENDER_TEXT_HARFBUZZ),
4095 PrintRenderTextBackend()); 4110 PrintRenderTextBackend());
4096 #endif 4111 #endif
4097 4112
4098 INSTANTIATE_TEST_CASE_P(, 4113 INSTANTIATE_TEST_CASE_P(,
4099 RenderTextHarfBuzzTest, 4114 RenderTextHarfBuzzTest,
4100 ::testing::Values(RENDER_TEXT_HARFBUZZ), 4115 ::testing::Values(RENDER_TEXT_HARFBUZZ),
4101 PrintRenderTextBackend()); 4116 PrintRenderTextBackend());
4102 4117
4103 } // namespace gfx 4118 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698