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

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

Issue 1070223004: Stop combining text runs which are connected by 'COMMON' blocks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make sure multiline breaker behavior is correct. Created 5 years, 8 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 } 83 }
84 // Check that cursoring is clamped at the line edge. 84 // Check that cursoring is clamped at the line edge.
85 EXPECT_EQ(expected.back(), render_text->selection_model()); 85 EXPECT_EQ(expected.back(), render_text->selection_model());
86 // Check that it is the line edge. 86 // Check that it is the line edge.
87 render_text->MoveCursor(LINE_BREAK, direction, false); 87 render_text->MoveCursor(LINE_BREAK, direction, false);
88 EXPECT_EQ(expected.back(), render_text->selection_model()); 88 EXPECT_EQ(expected.back(), render_text->selection_model());
89 } 89 }
90 #endif // !defined(OS_MACOSX) 90 #endif // !defined(OS_MACOSX)
91 91
92 // Test utility for Multiline_Newline test case. Empty |expected_range| means 92 // Test utility for Multiline_Newline test case. Empty |expected_range| means
93 // the blank line which has no segments. Otherwise |segments| should contain 93 // the blank line which has no segments. Otherwise |segment|'s range should
94 // exactly one line segment whose range equals to |expected_range|. 94 // equal to |expected_range|.
95 void VerifyLineSegments(const Range& expected_range, 95 void VerifyLineSegments(const Range& expected_range,
96 const std::vector<internal::LineSegment>& segments) { 96 const internal::LineSegment& segment) {
97 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size());
98 if (!expected_range.is_empty()) 97 if (!expected_range.is_empty())
99 EXPECT_EQ(expected_range, segments[0].char_range); 98 EXPECT_EQ(expected_range, segment.char_range);
100 } 99 }
101 100
102 // The class which records the drawing operations so that the test case can 101 // The class which records the drawing operations so that the test case can
103 // verify where exactly the glyphs are drawn. 102 // verify where exactly the glyphs are drawn.
104 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { 103 class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
105 public: 104 public:
106 struct TextLog { 105 struct TextLog {
107 TextLog() : glyph_count(0u) {} 106 TextLog() : glyph_count(0u) {}
108 PointF origin; 107 PointF origin;
109 size_t glyph_count; 108 size_t glyph_count;
(...skipping 1997 matching lines...) Expand 10 before | Expand all | Expand 10 after
2107 const wchar_t* const text; 2106 const wchar_t* const text;
2108 const Range first_line_char_range; 2107 const Range first_line_char_range;
2109 const Range second_line_char_range; 2108 const Range second_line_char_range;
2110 bool is_ltr; 2109 bool is_ltr;
2111 } kTestStrings[] = { 2110 } kTestStrings[] = {
2112 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, 2111 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true },
2113 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, 2112 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true },
2114 { L"\x0627\x0644\x0644\x063A\x0629 " 2113 { L"\x0627\x0644\x0644\x063A\x0629 "
2115 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", 2114 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
2116 Range(0, 6), Range(6, 13), false }, 2115 Range(0, 6), Range(6, 13), false },
2117 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" 2116 { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
2118 L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } 2117 L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false }
2119 }; 2118 };
2120 2119
2121 RenderTextHarfBuzz render_text; 2120 RenderTextHarfBuzz render_text;
2122 // Specify the fixed width for characters to suppress the possible variations 2121 // Specify the fixed width for characters to suppress the possible variations
2123 // of linebreak results. 2122 // of linebreak results.
2124 render_text.set_glyph_width_for_test(5); 2123 render_text.set_glyph_width_for_test(5);
2125 render_text.SetDisplayRect(Rect(50, 1000)); 2124 render_text.SetDisplayRect(Rect(50, 1000));
2126 render_text.SetMultiline(true); 2125 render_text.SetMultiline(true);
2127 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); 2126 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS);
2128 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); 2127 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 } 2185 }
2187 2186
2188 TEST_F(RenderTextTest, Multiline_Newline) { 2187 TEST_F(RenderTextTest, Multiline_Newline) {
2189 const struct { 2188 const struct {
2190 const wchar_t* const text; 2189 const wchar_t* const text;
2191 const size_t lines_count; 2190 const size_t lines_count;
2192 // Ranges of the characters on each line preceding the newline. 2191 // Ranges of the characters on each line preceding the newline.
2193 const Range line_char_ranges[3]; 2192 const Range line_char_ranges[3];
2194 } kTestStrings[] = { 2193 } kTestStrings[] = {
2195 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } }, 2194 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } },
2196 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 6), Range::InvalidRange() } }, 2195 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 4), Range(4, 6) } },
2197 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } }, 2196 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } },
2198 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } }, 2197 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } },
2199 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } }, 2198 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } },
2200 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } }, 2199 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } },
2201 }; 2200 };
2202 2201
2203 RenderTextHarfBuzz render_text; 2202 RenderTextHarfBuzz render_text;
2204 render_text.SetDisplayRect(Rect(200, 1000)); 2203 render_text.SetDisplayRect(Rect(200, 1000));
2205 render_text.SetMultiline(true); 2204 render_text.SetMultiline(true);
2206 Canvas canvas; 2205 Canvas canvas;
2207 2206
2208 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2207 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2209 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 2208 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2210 render_text.SetText(WideToUTF16(kTestStrings[i].text)); 2209 render_text.SetText(WideToUTF16(kTestStrings[i].text));
2211 render_text.Draw(&canvas); 2210 render_text.Draw(&canvas);
2212 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); 2211 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size());
2213 if (kTestStrings[i].lines_count != render_text.lines_.size()) 2212 if (kTestStrings[i].lines_count != render_text.lines_.size())
2214 continue; 2213 continue;
2215 2214
2216 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { 2215 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) {
2217 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); 2216 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j));
2218 VerifyLineSegments(kTestStrings[i].line_char_ranges[j], 2217 // There might be multiple segments in one line.
2219 render_text.lines_[j].segments); 2218 for (size_t k = 0; k < render_text.lines_[j].segments.size(); ++k) {
2219 VerifyLineSegments(kTestStrings[i].line_char_ranges[j + k],
2220 render_text.lines_[j].segments[k]);
2221 }
2220 } 2222 }
2221 } 2223 }
2222 } 2224 }
2223 2225
2224 // Make sure that multiline mode ignores elide behavior. 2226 // Make sure that multiline mode ignores elide behavior.
2225 TEST_F(RenderTextTest, Multiline_IgnoreElide) { 2227 TEST_F(RenderTextTest, Multiline_IgnoreElide) {
2226 const wchar_t kTestString[] = 2228 const wchar_t kTestString[] =
2227 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx"; 2229 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx";
2228 const wchar_t kEllipsis[] = L"\x2026"; 2230 const wchar_t kEllipsis[] = L"\x2026";
2229 2231
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2344 for (size_t j = 0; j < render_text.lines().size(); ++j) { 2346 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2345 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); 2347 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2346 EXPECT_EQ(kTestScenarios[i].char_ranges[j], 2348 EXPECT_EQ(kTestScenarios[i].char_ranges[j],
2347 render_text.lines()[j].segments[0].char_range); 2349 render_text.lines()[j].segments[0].char_range);
2348 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, 2350 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2349 render_text.lines()[j].size.width()); 2351 render_text.lines()[j].size.width());
2350 } 2352 }
2351 } 2353 }
2352 } 2354 }
2353 2355
2356 TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) {
2357 const int kGlyphSize = 5;
2358 const struct {
2359 const wchar_t* const text;
2360 const size_t num_lines;
2361 const Range char_ranges[3];
2362 } kTestScenarios[] = {
2363 { L"That's good. aaa", 3u,
2364 {Range(0, 7), Range(7, 13), Range(13, 16) } },
2365 {
2366 L"That's \"good\". aaa", 3u,
2367 {Range(0, 7), Range(7, 15), Range(15, 18) } }
2368 };
2369
2370 RenderTextHarfBuzz render_text;
2371 render_text.SetMultiline(true);
2372 render_text.set_glyph_width_for_test(kGlyphSize);
2373 render_text.SetDisplayRect(Rect(0, 0, kGlyphSize * 4, 0));
2374 render_text.SetWordWrapBehavior(IGNORE_LONG_WORDS);
2375
2376 Canvas canvas;
2377
2378 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) {
2379 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2380 render_text.SetText(WideToUTF16(kTestScenarios[i].text));
2381 render_text.Draw(&canvas);
2382
2383 ASSERT_EQ(kTestScenarios[i].num_lines, render_text.lines().size());
2384 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2385 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2386 // Merges all the segments ranges in the same line.
2387 size_t segment_size = render_text.lines()[j].segments.size();
2388 Range line_range(
2389 render_text.lines()[j].segments[0].char_range.start(),
2390 render_text.lines()[j].segments[segment_size - 1].char_range.end());
2391 EXPECT_EQ(kTestScenarios[i].char_ranges[j], line_range);
2392 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2393 render_text.lines()[j].size.width());
2394 }
2395 }
2396 }
2397
2354 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { 2398 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
2355 const wchar_t* kTestStrings[] = { 2399 const wchar_t* kTestStrings[] = {
2356 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", 2400 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n",
2357 }; 2401 };
2358 2402
2359 RenderTextHarfBuzz render_text; 2403 RenderTextHarfBuzz render_text;
2360 render_text.SetDisplayRect(Rect(200, 1000)); 2404 render_text.SetDisplayRect(Rect(200, 1000));
2361 Canvas canvas; 2405 Canvas canvas;
2362 2406
2363 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2407 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2589 render_text.EnsureLayout(); 2633 render_text.EnsureLayout();
2590 internal::TextRunList* run_list = render_text.GetRunList(); 2634 internal::TextRunList* run_list = render_text.GetRunList();
2591 ASSERT_EQ(3U, run_list->size()); 2635 ASSERT_EQ(3U, run_list->size());
2592 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); 2636 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
2593 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); 2637 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
2594 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); 2638 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
2595 2639
2596 render_text.SetText(WideToUTF16(L"x \x25B6 y")); 2640 render_text.SetText(WideToUTF16(L"x \x25B6 y"));
2597 render_text.EnsureLayout(); 2641 render_text.EnsureLayout();
2598 run_list = render_text.GetRunList(); 2642 run_list = render_text.GetRunList();
2599 ASSERT_EQ(3U, run_list->size()); 2643 ASSERT_EQ(4U, run_list->size());
2600 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); 2644 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
2601 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); 2645 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
2602 EXPECT_EQ(Range(3, 5), run_list->runs()[2]->range); 2646 EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
2647 EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
2603 } 2648 }
2604 2649
2605 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { 2650 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) {
2606 RenderTextHarfBuzz render_text; 2651 RenderTextHarfBuzz render_text;
2607 2652
2608 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is 2653 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is
2609 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be 2654 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be
2610 // separated. See crbug.com/448909 2655 // separated. See crbug.com/448909
2611 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); 2656 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
2612 render_text.EnsureLayout(); 2657 render_text.EnsureLayout();
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
2928 string_size.set_width(string_size.width() / 2); 2973 string_size.set_width(string_size.width() / 2);
2929 render_text.SetDisplayRect(gfx::Rect(string_size)); 2974 render_text.SetDisplayRect(gfx::Rect(string_size));
2930 render_text.EnsureLayout(); 2975 render_text.EnsureLayout();
2931 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); 2976 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_);
2932 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); 2977 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count));
2933 EXPECT_NE(0, glyph_count); 2978 EXPECT_NE(0, glyph_count);
2934 } 2979 }
2935 #endif 2980 #endif
2936 2981
2937 } // namespace gfx 2982 } // 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