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 |