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 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { |
| 94 public: |
| 95 struct TextLog { |
| 96 TextLog() : glyph_count(0u) {} |
| 97 gfx::Rect bounds; |
| 98 size_t glyph_count; |
| 99 }; |
| 100 |
| 101 struct DecorationLog { |
| 102 DecorationLog(int x, int y, int width, bool underline, bool strike, |
| 103 bool diagonal_strike) |
| 104 : x(x), y(y), width(width), underline(underline), strike(strike), |
| 105 diagonal_strike(diagonal_strike) {} |
| 106 int x; |
| 107 int y; |
| 108 int width; |
| 109 bool underline; |
| 110 bool strike; |
| 111 bool diagonal_strike; |
| 112 }; |
| 113 |
| 114 explicit TestSkiaTextRenderer(Canvas* canvas) |
| 115 : internal::SkiaTextRenderer(canvas) {} |
| 116 ~TestSkiaTextRenderer() override {} |
| 117 |
| 118 void GetDrawTextLogAndReset(std::vector<TextLog>* draw_text_log) { |
| 119 draw_text_log_.swap(*draw_text_log); |
| 120 draw_text_log_.clear(); |
| 121 } |
| 122 |
| 123 void GetDecorationLogAndReset(std::vector<DecorationLog>* decoration_log) { |
| 124 decoration_log_.swap(*decoration_log); |
| 125 decoration_log_.clear(); |
| 126 } |
| 127 |
| 128 private: |
| 129 // internal::SkiaTextRenderer: |
| 130 void DrawPosText(const SkPoint* pos, |
| 131 const uint16* glyphs, |
| 132 size_t glyph_count) override { |
| 133 TextLog log_entry; |
| 134 log_entry.glyph_count = glyph_count; |
| 135 for (size_t i = 0u; i < glyph_count; ++i) { |
| 136 log_entry.bounds.Union(gfx::Rect(pos[i].x(), pos[i].y(), 1, 1)); |
| 137 } |
| 138 draw_text_log_.push_back(log_entry); |
| 139 internal::SkiaTextRenderer::DrawPosText(pos, glyphs, glyph_count); |
| 140 } |
| 141 |
| 142 void DrawDecorations(int x, int y, int width, bool underline, bool strike, |
| 143 bool diagonal_strike) override { |
| 144 decoration_log_.push_back( |
| 145 DecorationLog(x, y, width, underline, strike, diagonal_strike)); |
| 146 internal::SkiaTextRenderer::DrawDecorations( |
| 147 x, y, width, underline, strike, diagonal_strike); |
| 148 } |
| 149 |
| 150 std::vector<TextLog> draw_text_log_; |
| 151 std::vector<DecorationLog> decoration_log_; |
| 152 }; |
| 153 |
93 } // namespace | 154 } // namespace |
94 | 155 |
95 class RenderTextTest : public testing::Test { | 156 class RenderTextTest : public testing::Test { |
96 }; | 157 }; |
97 | 158 |
98 TEST_F(RenderTextTest, DefaultStyle) { | 159 TEST_F(RenderTextTest, DefaultStyle) { |
99 // Check the default styles applied to new instances and adjusted text. | 160 // Check the default styles applied to new instances and adjusted text. |
100 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 161 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
101 EXPECT_TRUE(render_text->text().empty()); | 162 EXPECT_TRUE(render_text->text().empty()); |
102 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; | 163 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; |
(...skipping 1809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1912 EXPECT_GT(render_text.lines_.size(), 1U); | 1973 EXPECT_GT(render_text.lines_.size(), 1U); |
1913 } | 1974 } |
1914 } | 1975 } |
1915 | 1976 |
1916 // Ensure strings wrap onto multiple lines for a normal available width. | 1977 // Ensure strings wrap onto multiple lines for a normal available width. |
1917 TEST_F(RenderTextTest, Multiline_NormalWidth) { | 1978 TEST_F(RenderTextTest, Multiline_NormalWidth) { |
1918 const struct { | 1979 const struct { |
1919 const wchar_t* const text; | 1980 const wchar_t* const text; |
1920 const Range first_line_char_range; | 1981 const Range first_line_char_range; |
1921 const Range second_line_char_range; | 1982 const Range second_line_char_range; |
| 1983 bool is_ltr; |
1922 } kTestStrings[] = { | 1984 } kTestStrings[] = { |
1923 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, | 1985 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, |
1924 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12) }, | 1986 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, |
| 1987 { L"\x0627\x0644\x0644\x063A\x0629 " |
| 1988 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", |
| 1989 Range(0, 6), Range(6, 13), false }, |
1925 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" | 1990 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" |
1926 L"\x05DA\x05DB\x05DD", Range(4, 12), Range(0, 4) } | 1991 L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } |
1927 }; | 1992 }; |
1928 | 1993 |
1929 RenderTextHarfBuzz render_text; | 1994 RenderTextHarfBuzz render_text; |
1930 // Specify the fixed width for characters to suppress the possible variations | 1995 // Specify the fixed width for characters to suppress the possible variations |
1931 // of linebreak results. | 1996 // of linebreak results. |
1932 render_text.set_glyph_width_for_test(5); | 1997 render_text.set_glyph_width_for_test(5); |
1933 render_text.SetDisplayRect(Rect(50, 1000)); | 1998 render_text.SetDisplayRect(Rect(50, 1000)); |
1934 render_text.SetMultiline(true); | 1999 render_text.SetMultiline(true); |
| 2000 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); |
| 2001 |
1935 Canvas canvas; | 2002 Canvas canvas; |
| 2003 TestSkiaTextRenderer renderer(&canvas); |
1936 | 2004 |
1937 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2005 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
1938 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 2006 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
1939 render_text.SetText(WideToUTF16(kTestStrings[i].text)); | 2007 render_text.SetText(WideToUTF16(kTestStrings[i].text)); |
1940 render_text.Draw(&canvas); | 2008 render_text.EnsureLayout(); |
| 2009 render_text.DrawVisualTextInternal(&renderer); |
| 2010 |
1941 ASSERT_EQ(2U, render_text.lines_.size()); | 2011 ASSERT_EQ(2U, render_text.lines_.size()); |
1942 ASSERT_EQ(1U, render_text.lines_[0].segments.size()); | 2012 ASSERT_EQ(1U, render_text.lines_[0].segments.size()); |
1943 EXPECT_EQ(kTestStrings[i].first_line_char_range, | 2013 EXPECT_EQ(kTestStrings[i].first_line_char_range, |
1944 render_text.lines_[0].segments[0].char_range); | 2014 render_text.lines_[0].segments[0].char_range); |
1945 ASSERT_EQ(1U, render_text.lines_[1].segments.size()); | 2015 ASSERT_EQ(1U, render_text.lines_[1].segments.size()); |
1946 EXPECT_EQ(kTestStrings[i].second_line_char_range, | 2016 EXPECT_EQ(kTestStrings[i].second_line_char_range, |
1947 render_text.lines_[1].segments[0].char_range); | 2017 render_text.lines_[1].segments[0].char_range); |
| 2018 |
| 2019 std::vector<TestSkiaTextRenderer::TextLog> draw_text_log; |
| 2020 renderer.GetDrawTextLogAndReset(&draw_text_log); |
| 2021 ASSERT_EQ(2U, draw_text_log.size()); |
| 2022 EXPECT_EQ(kTestStrings[i].first_line_char_range.length(), |
| 2023 draw_text_log[0].glyph_count); |
| 2024 EXPECT_EQ(kTestStrings[i].second_line_char_range.length(), |
| 2025 draw_text_log[1].glyph_count); |
| 2026 EXPECT_LT(draw_text_log[0].bounds.y(), draw_text_log[1].bounds.y()); |
| 2027 if (kTestStrings[i].is_ltr) { |
| 2028 EXPECT_EQ(0, draw_text_log[0].bounds.x()); |
| 2029 EXPECT_EQ(0, draw_text_log[1].bounds.x()); |
| 2030 } else { |
| 2031 EXPECT_LT(0, draw_text_log[0].bounds.x()); |
| 2032 EXPECT_LT(0, draw_text_log[1].bounds.x()); |
| 2033 } |
1948 } | 2034 } |
1949 } | 2035 } |
1950 | 2036 |
1951 // Ensure strings don't wrap onto multiple lines for a sufficient available | 2037 // Ensure strings don't wrap onto multiple lines for a sufficient available |
1952 // width. | 2038 // width. |
1953 TEST_F(RenderTextTest, Multiline_SufficientWidth) { | 2039 TEST_F(RenderTextTest, Multiline_SufficientWidth) { |
1954 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", | 2040 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", |
1955 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; | 2041 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; |
1956 | 2042 |
1957 RenderTextHarfBuzz render_text; | 2043 RenderTextHarfBuzz render_text; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2014 | 2100 |
2015 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2101 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
2016 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 2102 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
2017 render_text.SetText(WideToUTF16(kTestStrings[i])); | 2103 render_text.SetText(WideToUTF16(kTestStrings[i])); |
2018 render_text.Draw(&canvas); | 2104 render_text.Draw(&canvas); |
2019 | 2105 |
2020 EXPECT_EQ(1U, render_text.lines_.size()); | 2106 EXPECT_EQ(1U, render_text.lines_.size()); |
2021 } | 2107 } |
2022 } | 2108 } |
2023 | 2109 |
| 2110 TEST_F(RenderTextTest, HarfBuzz_RTLDrawingPositions) { |
| 2111 RenderTextHarfBuzz render_text; |
| 2112 render_text.SetText(WideToUTF16( |
| 2113 L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" |
| 2114 L"\x05DA\x05DB\x05DD")); |
| 2115 |
| 2116 Canvas canvas; |
| 2117 TestSkiaTextRenderer renderer(&canvas); |
| 2118 |
| 2119 render_text.EnsureLayout(); |
| 2120 render_text.DrawVisualTextInternal(&renderer); |
| 2121 |
| 2122 std::vector<TestSkiaTextRenderer::TextLog> draw_text_log; |
| 2123 renderer.GetDrawTextLogAndReset(&draw_text_log); |
| 2124 |
| 2125 EXPECT_EQ(2U, draw_text_log.size()); |
| 2126 |
| 2127 EXPECT_EQ(8U, draw_text_log[0].glyph_count); |
| 2128 EXPECT_EQ(4U, draw_text_log[1].glyph_count); |
| 2129 EXPECT_LT(draw_text_log[0].bounds.x(), draw_text_log[1].bounds.x()); |
| 2130 } |
| 2131 |
| 2132 // Verifies the drawing position when the glyph's width is fractional. |
| 2133 // See http://crbug.com/456692 |
| 2134 TEST_F(RenderTextTest, HarfBuzz_TextPositionWithFractionalSize) { |
| 2135 RenderTextHarfBuzz render_text; |
| 2136 render_text.SetCursorEnabled(false); |
| 2137 render_text.set_glyph_width_for_test(5.5); |
| 2138 |
| 2139 render_text.SetText(ASCIIToUTF16("speed test")); |
| 2140 render_text.ApplyStyle(UNDERLINE, true, Range(1, 10)); |
| 2141 |
| 2142 Canvas canvas; |
| 2143 TestSkiaTextRenderer renderer(&canvas); |
| 2144 render_text.EnsureLayout(); |
| 2145 render_text.DrawVisualTextInternal(&renderer); |
| 2146 |
| 2147 std::vector<TestSkiaTextRenderer::TextLog> draw_text_log; |
| 2148 std::vector<TestSkiaTextRenderer::DecorationLog> decoration_log; |
| 2149 renderer.GetDrawTextLogAndReset(&draw_text_log); |
| 2150 renderer.GetDecorationLogAndReset(&decoration_log); |
| 2151 |
| 2152 EXPECT_EQ(2u, draw_text_log.size()); |
| 2153 EXPECT_EQ(2u, decoration_log.size()); |
| 2154 |
| 2155 EXPECT_EQ(1u, draw_text_log[0].glyph_count); |
| 2156 EXPECT_EQ(9u, draw_text_log[1].glyph_count); |
| 2157 EXPECT_EQ(0, draw_text_log[0].bounds.x()); |
| 2158 EXPECT_EQ(6, draw_text_log[1].bounds.x()); |
| 2159 |
| 2160 EXPECT_EQ(draw_text_log[0].bounds.x(), decoration_log[0].x); |
| 2161 EXPECT_EQ(draw_text_log[1].bounds.x(), decoration_log[1].x); |
| 2162 EXPECT_FALSE(decoration_log[0].underline); |
| 2163 EXPECT_TRUE(decoration_log[1].underline); |
| 2164 } |
| 2165 |
2024 // Test TextRunHarfBuzz's cluster finding logic. | 2166 // Test TextRunHarfBuzz's cluster finding logic. |
2025 TEST_F(RenderTextTest, HarfBuzz_Clusters) { | 2167 TEST_F(RenderTextTest, HarfBuzz_Clusters) { |
2026 struct { | 2168 struct { |
2027 uint32 glyph_to_char[4]; | 2169 uint32 glyph_to_char[4]; |
2028 Range chars[4]; | 2170 Range chars[4]; |
2029 Range glyphs[4]; | 2171 Range glyphs[4]; |
2030 bool is_rtl; | 2172 bool is_rtl; |
2031 } cases[] = { | 2173 } cases[] = { |
2032 { // From string "A B C D" to glyphs "a b c d". | 2174 { // From string "A B C D" to glyphs "a b c d". |
2033 { 0, 1, 2, 3 }, | 2175 { 0, 1, 2, 3 }, |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2383 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); | 2525 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); |
2384 | 2526 |
2385 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 2527 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
2386 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); | 2528 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); |
2387 render_text->SetFontList(font_list); | 2529 render_text->SetFontList(font_list); |
2388 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); | 2530 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); |
2389 } | 2531 } |
2390 #endif | 2532 #endif |
2391 | 2533 |
2392 } // namespace gfx | 2534 } // namespace gfx |
OLD | NEW |