Chromium Code Reviews| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 // Test utility for Multiline_Newline test case. Empty |expected_range| means | 83 // Test utility for Multiline_Newline test case. Empty |expected_range| means |
| 84 // the blank line which has no segments. Otherwise |segments| should contain | 84 // the blank line which has no segments. Otherwise |segments| should contain |
| 85 // exactly one line segment whose range equals to |expected_range|. | 85 // exactly one line segment whose range equals to |expected_range|. |
| 86 void VerifyLineSegments(const Range& expected_range, | 86 void VerifyLineSegments(const Range& expected_range, |
| 87 const std::vector<internal::LineSegment>& segments) { | 87 const std::vector<internal::LineSegment>& segments) { |
| 88 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size()); | 88 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size()); |
| 89 if (!expected_range.is_empty()) | 89 if (!expected_range.is_empty()) |
| 90 EXPECT_EQ(expected_range, segments[0].char_range); | 90 EXPECT_EQ(expected_range, segments[0].char_range); |
| 91 } | 91 } |
| 92 | 92 |
| 93 // The class which records the drawing operations so that the test case can | |
| 94 // verify where exactly the glyphs are drawn. | |
| 95 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { | |
| 96 public: | |
| 97 struct TextLog { | |
| 98 TextLog() : glyph_count(0u) {} | |
| 99 PointF origin; | |
| 100 size_t glyph_count; | |
| 101 }; | |
| 102 | |
| 103 struct DecorationLog { | |
| 104 DecorationLog(int x, int y, int width, bool underline, bool strike, | |
| 105 bool diagonal_strike) | |
| 106 : x(x), y(y), width(width), underline(underline), strike(strike), | |
| 107 diagonal_strike(diagonal_strike) {} | |
| 108 int x; | |
| 109 int y; | |
| 110 int width; | |
| 111 bool underline; | |
| 112 bool strike; | |
| 113 bool diagonal_strike; | |
| 114 }; | |
| 115 | |
| 116 explicit TestSkiaTextRenderer(Canvas* canvas) | |
| 117 : internal::SkiaTextRenderer(canvas) {} | |
| 118 ~TestSkiaTextRenderer() override {} | |
| 119 | |
| 120 void GetTextLogAndReset(std::vector<TextLog>* text_log) { | |
| 121 text_log_.swap(*text_log); | |
| 122 text_log_.clear(); | |
| 123 } | |
| 124 | |
| 125 void GetDecorationLogAndReset(std::vector<DecorationLog>* decoration_log) { | |
| 126 decoration_log_.swap(*decoration_log); | |
| 127 decoration_log_.clear(); | |
| 128 } | |
| 129 | |
| 130 private: | |
| 131 // internal::SkiaTextRenderer: | |
| 132 void DrawPosText(const SkPoint* pos, | |
| 133 const uint16* glyphs, | |
| 134 size_t glyph_count) override { | |
| 135 TextLog log_entry; | |
| 136 log_entry.glyph_count = glyph_count; | |
| 137 if (glyph_count > 0) { | |
| 138 log_entry.origin = | |
| 139 PointF(SkScalarToFloat(pos[0].x()), SkScalarToFloat(pos[0].y())); | |
| 140 for (size_t i = 1U; i < glyph_count; ++i) { | |
| 141 log_entry.origin.SetToMin( | |
| 142 PointF(SkScalarToFloat(pos[i].x()), SkScalarToFloat(pos[i].y()))); | |
| 143 } | |
| 144 } | |
| 145 text_log_.push_back(log_entry); | |
| 146 internal::SkiaTextRenderer::DrawPosText(pos, glyphs, glyph_count); | |
| 147 } | |
| 148 | |
| 149 void DrawDecorations(int x, int y, int width, bool underline, bool strike, | |
| 150 bool diagonal_strike) override { | |
| 151 decoration_log_.push_back( | |
| 152 DecorationLog(x, y, width, underline, strike, diagonal_strike)); | |
| 153 internal::SkiaTextRenderer::DrawDecorations( | |
| 154 x, y, width, underline, strike, diagonal_strike); | |
| 155 } | |
| 156 | |
| 157 std::vector<TextLog> text_log_; | |
| 158 std::vector<DecorationLog> decoration_log_; | |
| 159 }; | |
|
msw
2015/02/18 18:58:37
nit: DISALLOW_COPY_AND_ASSIGN
Jun Mukai
2015/02/18 19:55:56
Done.
| |
| 160 | |
| 93 } // namespace | 161 } // namespace |
| 94 | 162 |
| 95 class RenderTextTest : public testing::Test { | 163 class RenderTextTest : public testing::Test { |
| 96 }; | 164 }; |
| 97 | 165 |
| 98 TEST_F(RenderTextTest, DefaultStyle) { | 166 TEST_F(RenderTextTest, DefaultStyle) { |
| 99 // Check the default styles applied to new instances and adjusted text. | 167 // Check the default styles applied to new instances and adjusted text. |
| 100 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 168 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 101 EXPECT_TRUE(render_text->text().empty()); | 169 EXPECT_TRUE(render_text->text().empty()); |
| 102 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; | 170 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; |
| (...skipping 1807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1910 EXPECT_GT(render_text.lines_.size(), 1U); | 1978 EXPECT_GT(render_text.lines_.size(), 1U); |
| 1911 } | 1979 } |
| 1912 } | 1980 } |
| 1913 | 1981 |
| 1914 // Ensure strings wrap onto multiple lines for a normal available width. | 1982 // Ensure strings wrap onto multiple lines for a normal available width. |
| 1915 TEST_F(RenderTextTest, Multiline_NormalWidth) { | 1983 TEST_F(RenderTextTest, Multiline_NormalWidth) { |
| 1916 const struct { | 1984 const struct { |
| 1917 const wchar_t* const text; | 1985 const wchar_t* const text; |
| 1918 const Range first_line_char_range; | 1986 const Range first_line_char_range; |
| 1919 const Range second_line_char_range; | 1987 const Range second_line_char_range; |
| 1988 bool is_ltr; | |
| 1920 } kTestStrings[] = { | 1989 } kTestStrings[] = { |
| 1921 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, | 1990 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, |
| 1922 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12) }, | 1991 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, |
| 1992 { L"\x0627\x0644\x0644\x063A\x0629 " | |
| 1993 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", | |
| 1994 Range(0, 6), Range(6, 13), false }, | |
| 1923 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" | 1995 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" |
| 1924 L"\x05DA\x05DB\x05DD", Range(4, 12), Range(0, 4) } | 1996 L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } |
| 1925 }; | 1997 }; |
| 1926 | 1998 |
| 1927 RenderTextHarfBuzz render_text; | 1999 RenderTextHarfBuzz render_text; |
| 1928 // Specify the fixed width for characters to suppress the possible variations | 2000 // Specify the fixed width for characters to suppress the possible variations |
| 1929 // of linebreak results. | 2001 // of linebreak results. |
| 1930 render_text.set_glyph_width_for_test(5); | 2002 render_text.set_glyph_width_for_test(5); |
| 1931 render_text.SetDisplayRect(Rect(50, 1000)); | 2003 render_text.SetDisplayRect(Rect(50, 1000)); |
| 1932 render_text.SetMultiline(true); | 2004 render_text.SetMultiline(true); |
| 2005 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); | |
| 2006 | |
| 1933 Canvas canvas; | 2007 Canvas canvas; |
| 2008 TestSkiaTextRenderer renderer(&canvas); | |
| 1934 | 2009 |
| 1935 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2010 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1936 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 2011 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1937 render_text.SetText(WideToUTF16(kTestStrings[i].text)); | 2012 render_text.SetText(WideToUTF16(kTestStrings[i].text)); |
| 1938 render_text.Draw(&canvas); | 2013 render_text.EnsureLayout(); |
| 2014 render_text.DrawVisualTextInternal(&renderer); | |
| 2015 | |
| 1939 ASSERT_EQ(2U, render_text.lines_.size()); | 2016 ASSERT_EQ(2U, render_text.lines_.size()); |
| 1940 ASSERT_EQ(1U, render_text.lines_[0].segments.size()); | 2017 ASSERT_EQ(1U, render_text.lines_[0].segments.size()); |
| 1941 EXPECT_EQ(kTestStrings[i].first_line_char_range, | 2018 EXPECT_EQ(kTestStrings[i].first_line_char_range, |
| 1942 render_text.lines_[0].segments[0].char_range); | 2019 render_text.lines_[0].segments[0].char_range); |
| 1943 ASSERT_EQ(1U, render_text.lines_[1].segments.size()); | 2020 ASSERT_EQ(1U, render_text.lines_[1].segments.size()); |
| 1944 EXPECT_EQ(kTestStrings[i].second_line_char_range, | 2021 EXPECT_EQ(kTestStrings[i].second_line_char_range, |
| 1945 render_text.lines_[1].segments[0].char_range); | 2022 render_text.lines_[1].segments[0].char_range); |
| 2023 | |
| 2024 std::vector<TestSkiaTextRenderer::TextLog> text_log; | |
| 2025 renderer.GetTextLogAndReset(&text_log); | |
| 2026 ASSERT_EQ(2U, text_log.size()); | |
| 2027 // NOTE: this expectation compares the character length and glyph counts, | |
| 2028 // which doesn't always equal. This is okay only because the all test | |
|
msw
2015/02/18 18:58:37
nit: s/doesn't/isn't/ and s/the all test/all the t
Jun Mukai
2015/02/18 19:55:56
Done.
| |
| 2029 // strings are simple (like, no compound characters nor UTF16-surrogate | |
| 2030 // pairs). Be careful in case more complicated test strings are added. | |
| 2031 EXPECT_EQ(kTestStrings[i].first_line_char_range.length(), | |
| 2032 text_log[0].glyph_count); | |
| 2033 EXPECT_EQ(kTestStrings[i].second_line_char_range.length(), | |
| 2034 text_log[1].glyph_count); | |
| 2035 EXPECT_LT(text_log[0].origin.y(), text_log[1].origin.y()); | |
| 2036 if (kTestStrings[i].is_ltr) { | |
| 2037 EXPECT_EQ(0, text_log[0].origin.x()); | |
| 2038 EXPECT_EQ(0, text_log[1].origin.x()); | |
| 2039 } else { | |
| 2040 EXPECT_LT(0, text_log[0].origin.x()); | |
| 2041 EXPECT_LT(0, text_log[1].origin.x()); | |
| 2042 } | |
| 1946 } | 2043 } |
| 1947 } | 2044 } |
| 1948 | 2045 |
| 1949 // Ensure strings don't wrap onto multiple lines for a sufficient available | 2046 // Ensure strings don't wrap onto multiple lines for a sufficient available |
| 1950 // width. | 2047 // width. |
| 1951 TEST_F(RenderTextTest, Multiline_SufficientWidth) { | 2048 TEST_F(RenderTextTest, Multiline_SufficientWidth) { |
| 1952 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", | 2049 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", |
| 1953 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; | 2050 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; |
| 1954 | 2051 |
| 1955 RenderTextHarfBuzz render_text; | 2052 RenderTextHarfBuzz render_text; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2030 | 2127 |
| 2031 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2128 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 2032 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 2129 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 2033 render_text.SetText(WideToUTF16(kTestStrings[i])); | 2130 render_text.SetText(WideToUTF16(kTestStrings[i])); |
| 2034 render_text.Draw(&canvas); | 2131 render_text.Draw(&canvas); |
| 2035 | 2132 |
| 2036 EXPECT_EQ(1U, render_text.lines_.size()); | 2133 EXPECT_EQ(1U, render_text.lines_.size()); |
| 2037 } | 2134 } |
| 2038 } | 2135 } |
| 2039 | 2136 |
| 2137 TEST_F(RenderTextTest, HarfBuzz_RTLDrawingPositions) { | |
| 2138 RenderTextHarfBuzz render_text; | |
| 2139 render_text.SetText(WideToUTF16( | |
| 2140 L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" | |
| 2141 L"\x05DA\x05DB\x05DD")); | |
| 2142 | |
| 2143 Canvas canvas; | |
| 2144 TestSkiaTextRenderer renderer(&canvas); | |
| 2145 | |
| 2146 render_text.EnsureLayout(); | |
| 2147 render_text.DrawVisualTextInternal(&renderer); | |
| 2148 | |
| 2149 std::vector<TestSkiaTextRenderer::TextLog> text_log; | |
| 2150 renderer.GetTextLogAndReset(&text_log); | |
| 2151 | |
| 2152 EXPECT_EQ(2U, text_log.size()); | |
| 2153 | |
| 2154 EXPECT_EQ(8U, text_log[0].glyph_count); | |
| 2155 EXPECT_EQ(4U, text_log[1].glyph_count); | |
| 2156 EXPECT_LT(text_log[0].origin.x(), text_log[1].origin.x()); | |
| 2157 } | |
| 2158 | |
| 2040 // Test TextRunHarfBuzz's cluster finding logic. | 2159 // Test TextRunHarfBuzz's cluster finding logic. |
| 2041 TEST_F(RenderTextTest, HarfBuzz_Clusters) { | 2160 TEST_F(RenderTextTest, HarfBuzz_Clusters) { |
| 2042 struct { | 2161 struct { |
| 2043 uint32 glyph_to_char[4]; | 2162 uint32 glyph_to_char[4]; |
| 2044 Range chars[4]; | 2163 Range chars[4]; |
| 2045 Range glyphs[4]; | 2164 Range glyphs[4]; |
| 2046 bool is_rtl; | 2165 bool is_rtl; |
| 2047 } cases[] = { | 2166 } cases[] = { |
| 2048 { // From string "A B C D" to glyphs "a b c d". | 2167 { // From string "A B C D" to glyphs "a b c d". |
| 2049 { 0, 1, 2, 3 }, | 2168 { 0, 1, 2, 3 }, |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2406 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); | 2525 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); |
| 2407 | 2526 |
| 2408 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 2527 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 2409 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); | 2528 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); |
| 2410 render_text->SetFontList(font_list); | 2529 render_text->SetFontList(font_list); |
| 2411 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); | 2530 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); |
| 2412 } | 2531 } |
| 2413 #endif | 2532 #endif |
| 2414 | 2533 |
| 2415 } // namespace gfx | 2534 } // namespace gfx |
| OLD | NEW |