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

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

Issue 924773002: Fix multiline behaviors for RTL text. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months 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 <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
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
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
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
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
OLDNEW
« ui/gfx/render_text_harfbuzz.cc ('K') | « ui/gfx/render_text_harfbuzz.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698