| 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/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 render_text->MoveCursor(CHARACTER_BREAK, direction, false); | 73 render_text->MoveCursor(CHARACTER_BREAK, direction, false); |
| 74 } | 74 } |
| 75 // Check that cursoring is clamped at the line edge. | 75 // Check that cursoring is clamped at the line edge. |
| 76 EXPECT_EQ(expected.back(), render_text->selection_model()); | 76 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 77 // Check that it is the line edge. | 77 // Check that it is the line edge. |
| 78 render_text->MoveCursor(LINE_BREAK, direction, false); | 78 render_text->MoveCursor(LINE_BREAK, direction, false); |
| 79 EXPECT_EQ(expected.back(), render_text->selection_model()); | 79 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 80 } | 80 } |
| 81 #endif // !defined(OS_MACOSX) | 81 #endif // !defined(OS_MACOSX) |
| 82 | 82 |
| 83 // Test utility for Multiline_Newline test case. Empty |expected_range| means |
| 84 // the blank line which has no segments. Otherwise |segments| should contain |
| 85 // exactly one line segment whose range equals to |expected_range|. |
| 86 void VerifyLineSegments(const Range& expected_range, |
| 87 const std::vector<internal::LineSegment>& segments) { |
| 88 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size()); |
| 89 if (!expected_range.is_empty()) |
| 90 EXPECT_EQ(expected_range, segments[0].char_range); |
| 91 } |
| 92 |
| 83 } // namespace | 93 } // namespace |
| 84 | 94 |
| 85 class RenderTextTest : public testing::Test { | 95 class RenderTextTest : public testing::Test { |
| 86 }; | 96 }; |
| 87 | 97 |
| 88 TEST_F(RenderTextTest, DefaultStyle) { | 98 TEST_F(RenderTextTest, DefaultStyle) { |
| 89 // Check the default styles applied to new instances and adjusted text. | 99 // Check the default styles applied to new instances and adjusted text. |
| 90 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 100 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 91 EXPECT_TRUE(render_text->text().empty()); | 101 EXPECT_TRUE(render_text->text().empty()); |
| 92 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; | 102 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; |
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1866 render_text->SetText(WideToUTF16(kTestStrings[i])); |
| 1857 const int expected_width = render_text->GetStringSize().width(); | 1867 const int expected_width = render_text->GetStringSize().width(); |
| 1858 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); | 1868 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); |
| 1859 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); | 1869 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); |
| 1860 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119 | 1870 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119 |
| 1861 render_text->Draw(&canvas); | 1871 render_text->Draw(&canvas); |
| 1862 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); | 1872 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); |
| 1863 } | 1873 } |
| 1864 } | 1874 } |
| 1865 | 1875 |
| 1866 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | |
| 1867 // Ensure strings wrap onto multiple lines for a small available width. | 1876 // Ensure strings wrap onto multiple lines for a small available width. |
| 1868 TEST_F(RenderTextTest, DISABLED_Multiline_MinWidth) { | 1877 TEST_F(RenderTextTest, Multiline_MinWidth) { |
| 1869 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, | 1878 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, |
| 1870 kRtlLtr, kRtlLtrRtl }; | 1879 kRtlLtr, kRtlLtrRtl }; |
| 1871 | 1880 |
| 1872 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1881 RenderTextHarfBuzz render_text; |
| 1873 render_text->SetDisplayRect(Rect(1, 1000)); | 1882 render_text.SetDisplayRect(Rect(1, 1000)); |
| 1874 render_text->SetMultiline(true); | 1883 render_text.SetMultiline(true); |
| 1875 Canvas canvas; | 1884 Canvas canvas; |
| 1876 | 1885 |
| 1877 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1886 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1878 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1887 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1879 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1888 render_text.SetText(WideToUTF16(kTestStrings[i])); |
| 1880 render_text->Draw(&canvas); | 1889 render_text.Draw(&canvas); |
| 1881 EXPECT_GT(render_text->lines_.size(), 1U); | 1890 EXPECT_GT(render_text.lines_.size(), 1U); |
| 1882 } | 1891 } |
| 1883 } | 1892 } |
| 1884 | 1893 |
| 1885 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | |
| 1886 // Ensure strings wrap onto multiple lines for a normal available width. | 1894 // Ensure strings wrap onto multiple lines for a normal available width. |
| 1887 TEST_F(RenderTextTest, DISABLED_Multiline_NormalWidth) { | 1895 TEST_F(RenderTextTest, Multiline_NormalWidth) { |
| 1888 const struct { | 1896 const struct { |
| 1889 const wchar_t* const text; | 1897 const wchar_t* const text; |
| 1890 const Range first_line_char_range; | 1898 const Range first_line_char_range; |
| 1891 const Range second_line_char_range; | 1899 const Range second_line_char_range; |
| 1892 } kTestStrings[] = { | 1900 } kTestStrings[] = { |
| 1893 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, | 1901 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, |
| 1894 { L"qwertyzxcvbn", Range(0, 8), Range(8, 12) }, | 1902 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12) }, |
| 1895 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD", | 1903 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" |
| 1896 Range(4, 10), Range(0, 4) } | 1904 L"\x05DA\x05DB\x05DD", Range(4, 12), Range(0, 4) } |
| 1897 }; | 1905 }; |
| 1898 | 1906 |
| 1899 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1907 RenderTextHarfBuzz render_text; |
| 1900 render_text->SetDisplayRect(Rect(50, 1000)); | 1908 // Specify the fixed width for characters to suppress the possible variations |
| 1901 render_text->SetMultiline(true); | 1909 // of linebreak results. |
| 1910 render_text.set_glyph_width_for_test(5); |
| 1911 render_text.SetDisplayRect(Rect(50, 1000)); |
| 1912 render_text.SetMultiline(true); |
| 1902 Canvas canvas; | 1913 Canvas canvas; |
| 1903 | 1914 |
| 1904 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1915 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1905 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1916 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1906 render_text->SetText(WideToUTF16(kTestStrings[i].text)); | 1917 render_text.SetText(WideToUTF16(kTestStrings[i].text)); |
| 1907 render_text->Draw(&canvas); | 1918 render_text.Draw(&canvas); |
| 1908 ASSERT_EQ(2U, render_text->lines_.size()); | 1919 ASSERT_EQ(2U, render_text.lines_.size()); |
| 1909 ASSERT_EQ(1U, render_text->lines_[0].segments.size()); | 1920 ASSERT_EQ(1U, render_text.lines_[0].segments.size()); |
| 1910 EXPECT_EQ(kTestStrings[i].first_line_char_range, | 1921 EXPECT_EQ(kTestStrings[i].first_line_char_range, |
| 1911 render_text->lines_[0].segments[0].char_range); | 1922 render_text.lines_[0].segments[0].char_range); |
| 1912 ASSERT_EQ(1U, render_text->lines_[1].segments.size()); | 1923 ASSERT_EQ(1U, render_text.lines_[1].segments.size()); |
| 1913 EXPECT_EQ(kTestStrings[i].second_line_char_range, | 1924 EXPECT_EQ(kTestStrings[i].second_line_char_range, |
| 1914 render_text->lines_[1].segments[0].char_range); | 1925 render_text.lines_[1].segments[0].char_range); |
| 1915 } | 1926 } |
| 1916 } | 1927 } |
| 1917 | 1928 |
| 1918 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | |
| 1919 // Ensure strings don't wrap onto multiple lines for a sufficient available | 1929 // Ensure strings don't wrap onto multiple lines for a sufficient available |
| 1920 // width. | 1930 // width. |
| 1921 TEST_F(RenderTextTest, DISABLED_Multiline_SufficientWidth) { | 1931 TEST_F(RenderTextTest, Multiline_SufficientWidth) { |
| 1922 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", | 1932 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", |
| 1923 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; | 1933 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; |
| 1924 | 1934 |
| 1925 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1935 RenderTextHarfBuzz render_text; |
| 1926 render_text->SetDisplayRect(Rect(30, 1000)); | 1936 render_text.SetDisplayRect(Rect(1000, 1000)); |
| 1927 render_text->SetMultiline(true); | 1937 render_text.SetMultiline(true); |
| 1928 Canvas canvas; | 1938 Canvas canvas; |
| 1929 | 1939 |
| 1930 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1940 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1931 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1941 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1932 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1942 render_text.SetText(WideToUTF16(kTestStrings[i])); |
| 1933 render_text->Draw(&canvas); | 1943 render_text.Draw(&canvas); |
| 1934 EXPECT_EQ(1U, render_text->lines_.size()); | 1944 EXPECT_EQ(1U, render_text.lines_.size()); |
| 1935 } | 1945 } |
| 1936 } | 1946 } |
| 1937 | 1947 |
| 1938 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | 1948 TEST_F(RenderTextTest, Multiline_Newline) { |
| 1939 TEST_F(RenderTextTest, DISABLED_Multiline_Newline) { | |
| 1940 const struct { | 1949 const struct { |
| 1941 const wchar_t* const text; | 1950 const wchar_t* const text; |
| 1951 const size_t lines_count; |
| 1942 // Ranges of the characters on each line preceding the newline. | 1952 // Ranges of the characters on each line preceding the newline. |
| 1943 const Range first_line_char_range; | 1953 const Range line_char_ranges[3]; |
| 1944 const Range second_line_char_range; | |
| 1945 } kTestStrings[] = { | 1954 } kTestStrings[] = { |
| 1946 { L"abc\ndef", Range(0, 3), Range(4, 7) }, | 1955 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } }, |
| 1947 { L"a \n b ", Range(0, 2), Range(3, 6) }, | 1956 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 6), Range::InvalidRange() } }, |
| 1948 { L"\n" , Range::InvalidRange(), Range::InvalidRange() } | 1957 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } }, |
| 1958 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } }, |
| 1959 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } }, |
| 1960 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } }, |
| 1949 }; | 1961 }; |
| 1950 | 1962 |
| 1951 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1963 RenderTextHarfBuzz render_text; |
| 1952 render_text->SetDisplayRect(Rect(200, 1000)); | 1964 render_text.SetDisplayRect(Rect(200, 1000)); |
| 1953 render_text->SetMultiline(true); | 1965 render_text.SetMultiline(true); |
| 1954 Canvas canvas; | 1966 Canvas canvas; |
| 1955 | 1967 |
| 1956 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1968 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1957 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1969 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1958 render_text->SetText(WideToUTF16(kTestStrings[i].text)); | 1970 render_text.SetText(WideToUTF16(kTestStrings[i].text)); |
| 1959 render_text->Draw(&canvas); | 1971 render_text.Draw(&canvas); |
| 1972 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); |
| 1973 if (kTestStrings[i].lines_count != render_text.lines_.size()) |
| 1974 continue; |
| 1960 | 1975 |
| 1961 ASSERT_EQ(2U, render_text->lines_.size()); | 1976 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { |
| 1962 | 1977 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); |
| 1963 const Range first_expected_range = kTestStrings[i].first_line_char_range; | 1978 VerifyLineSegments(kTestStrings[i].line_char_ranges[j], |
| 1964 ASSERT_EQ(first_expected_range.IsValid() ? 2U : 1U, | 1979 render_text.lines_[j].segments); |
| 1965 render_text->lines_[0].segments.size()); | 1980 } |
| 1966 if (first_expected_range.IsValid()) | |
| 1967 EXPECT_EQ(first_expected_range, | |
| 1968 render_text->lines_[0].segments[0].char_range); | |
| 1969 | |
| 1970 const internal::LineSegment& newline_segment = | |
| 1971 render_text->lines_[0].segments[first_expected_range.IsValid() ? 1 : 0]; | |
| 1972 ASSERT_EQ(1U, newline_segment.char_range.length()); | |
| 1973 EXPECT_EQ(L'\n', kTestStrings[i].text[newline_segment.char_range.start()]); | |
| 1974 | |
| 1975 const Range second_expected_range = kTestStrings[i].second_line_char_range; | |
| 1976 ASSERT_EQ(second_expected_range.IsValid() ? 1U : 0U, | |
| 1977 render_text->lines_[1].segments.size()); | |
| 1978 if (second_expected_range.IsValid()) | |
| 1979 EXPECT_EQ(second_expected_range, | |
| 1980 render_text->lines_[1].segments[0].char_range); | |
| 1981 } | 1981 } |
| 1982 } | 1982 } |
| 1983 | 1983 |
| 1984 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { |
| 1985 const wchar_t* kTestStrings[] = { |
| 1986 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", |
| 1987 }; |
| 1988 |
| 1989 RenderTextHarfBuzz render_text; |
| 1990 render_text.SetDisplayRect(Rect(200, 1000)); |
| 1991 Canvas canvas; |
| 1992 |
| 1993 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1994 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1995 render_text.SetText(WideToUTF16(kTestStrings[i])); |
| 1996 render_text.Draw(&canvas); |
| 1997 |
| 1998 EXPECT_EQ(1U, render_text.lines_.size()); |
| 1999 } |
| 2000 } |
| 2001 |
| 1984 // Test TextRunHarfBuzz's cluster finding logic. | 2002 // Test TextRunHarfBuzz's cluster finding logic. |
| 1985 TEST_F(RenderTextTest, HarfBuzz_Clusters) { | 2003 TEST_F(RenderTextTest, HarfBuzz_Clusters) { |
| 1986 struct { | 2004 struct { |
| 1987 uint32 glyph_to_char[4]; | 2005 uint32 glyph_to_char[4]; |
| 1988 Range chars[4]; | 2006 Range chars[4]; |
| 1989 Range glyphs[4]; | 2007 Range glyphs[4]; |
| 1990 bool is_rtl; | 2008 bool is_rtl; |
| 1991 } cases[] = { | 2009 } cases[] = { |
| 1992 { // From string "A B C D" to glyphs "a b c d". | 2010 { // From string "A B C D" to glyphs "a b c d". |
| 1993 { 0, 1, 2, 3 }, | 2011 { 0, 1, 2, 3 }, |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2343 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); | 2361 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); |
| 2344 | 2362 |
| 2345 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 2363 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 2346 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); | 2364 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); |
| 2347 render_text->SetFontList(font_list); | 2365 render_text->SetFontList(font_list); |
| 2348 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); | 2366 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); |
| 2349 } | 2367 } |
| 2350 #endif | 2368 #endif |
| 2351 | 2369 |
| 2352 } // namespace gfx | 2370 } // namespace gfx |
| OLD | NEW |