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

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: Address Mukai's comments. Created 5 years, 7 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 render_text->MoveCursor(CHARACTER_BREAK, direction, false); 83 render_text->MoveCursor(CHARACTER_BREAK, direction, false);
84 } 84 }
85 // Check that cursoring is clamped at the line edge. 85 // Check that cursoring is clamped at the line edge.
86 EXPECT_EQ(expected.back(), render_text->selection_model()); 86 EXPECT_EQ(expected.back(), render_text->selection_model());
87 // Check that it is the line edge. 87 // Check that it is the line edge.
88 render_text->MoveCursor(LINE_BREAK, direction, false); 88 render_text->MoveCursor(LINE_BREAK, direction, false);
89 EXPECT_EQ(expected.back(), render_text->selection_model()); 89 EXPECT_EQ(expected.back(), render_text->selection_model());
90 } 90 }
91 #endif // !defined(OS_MACOSX) 91 #endif // !defined(OS_MACOSX)
92 92
93 // Test utility for Multiline_Newline test case. Empty |expected_range| means
94 // the blank line which has no segments. Otherwise |segments| should contain
95 // exactly one line segment whose range equals to |expected_range|.
96 void VerifyLineSegments(const Range& expected_range,
97 const std::vector<internal::LineSegment>& segments) {
98 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size());
99 if (!expected_range.is_empty())
100 EXPECT_EQ(expected_range, segments[0].char_range);
101 }
102
103 // The class which records the drawing operations so that the test case can 93 // The class which records the drawing operations so that the test case can
104 // verify where exactly the glyphs are drawn. 94 // verify where exactly the glyphs are drawn.
105 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { 95 class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
106 public: 96 public:
107 struct TextLog { 97 struct TextLog {
108 TextLog() : glyph_count(0u) {} 98 TextLog() : glyph_count(0u) {}
109 PointF origin; 99 PointF origin;
110 size_t glyph_count; 100 size_t glyph_count;
111 }; 101 };
112 102
(...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after
2121 const wchar_t* const text; 2111 const wchar_t* const text;
2122 const Range first_line_char_range; 2112 const Range first_line_char_range;
2123 const Range second_line_char_range; 2113 const Range second_line_char_range;
2124 bool is_ltr; 2114 bool is_ltr;
2125 } kTestStrings[] = { 2115 } kTestStrings[] = {
2126 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, 2116 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true },
2127 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, 2117 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true },
2128 { L"\x0627\x0644\x0644\x063A\x0629 " 2118 { L"\x0627\x0644\x0644\x063A\x0629 "
2129 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", 2119 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
2130 Range(0, 6), Range(6, 13), false }, 2120 Range(0, 6), Range(6, 13), false },
2131 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" 2121 { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
2132 L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } 2122 L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false }
2133 }; 2123 };
2134 2124
2135 RenderTextHarfBuzz render_text; 2125 RenderTextHarfBuzz render_text;
2136 // Specify the fixed width for characters to suppress the possible variations 2126 // Specify the fixed width for characters to suppress the possible variations
2137 // of linebreak results. 2127 // of linebreak results.
2138 render_text.set_glyph_width_for_test(5); 2128 render_text.set_glyph_width_for_test(5);
2139 render_text.SetDisplayRect(Rect(50, 1000)); 2129 render_text.SetDisplayRect(Rect(50, 1000));
2140 render_text.SetMultiline(true); 2130 render_text.SetMultiline(true);
2141 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); 2131 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS);
2142 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); 2132 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2212 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2223 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 2213 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2224 render_text.SetText(WideToUTF16(kTestStrings[i].text)); 2214 render_text.SetText(WideToUTF16(kTestStrings[i].text));
2225 render_text.Draw(&canvas); 2215 render_text.Draw(&canvas);
2226 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); 2216 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size());
2227 if (kTestStrings[i].lines_count != render_text.lines_.size()) 2217 if (kTestStrings[i].lines_count != render_text.lines_.size())
2228 continue; 2218 continue;
2229 2219
2230 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { 2220 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) {
2231 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); 2221 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j));
2232 VerifyLineSegments(kTestStrings[i].line_char_ranges[j], 2222 // There might be multiple segments in one line. Merge all the segments
msw 2015/05/27 17:38:00 Are there actually multiple segments in any of the
msw 2015/05/27 17:38:00 nit: "Merge all the segments ranges in the same li
xdai1 2015/06/01 16:51:16 Yes, for test case "a \n b", there are four runs h
xdai1 2015/06/01 16:51:16 Done.
2233 render_text.lines_[j].segments); 2223 // range.
2224 size_t segment_size = render_text.lines()[j].segments.size();
msw 2015/05/27 17:38:00 nit: const
xdai1 2015/06/01 16:51:16 Done.
2225 Range line_range;
2226 if (segment_size > 0)
2227 line_range = Range(
2228 render_text.lines()[j].segments[0].char_range.start(),
2229 render_text.lines()[j].segments[segment_size - 1].char_range.end());
msw 2015/05/27 17:38:00 Would we need to union all the ranges for RTL? Pro
xdai1 2015/06/01 16:51:16 I don't think so. This test function doesn't test
2230 EXPECT_EQ(kTestStrings[i].line_char_ranges[j], line_range);
2234 } 2231 }
2235 } 2232 }
2236 } 2233 }
2237 2234
2238 // Make sure that multiline mode ignores elide behavior. 2235 // Make sure that multiline mode ignores elide behavior.
2239 TEST_F(RenderTextTest, Multiline_IgnoreElide) { 2236 TEST_F(RenderTextTest, Multiline_IgnoreElide) {
2240 const wchar_t kTestString[] = 2237 const wchar_t kTestString[] =
2241 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx"; 2238 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx";
2242 const wchar_t kEllipsis[] = L"\x2026"; 2239 const wchar_t kEllipsis[] = L"\x2026";
2243 2240
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2358 for (size_t j = 0; j < render_text.lines().size(); ++j) { 2355 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2359 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); 2356 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2360 EXPECT_EQ(kTestScenarios[i].char_ranges[j], 2357 EXPECT_EQ(kTestScenarios[i].char_ranges[j],
2361 render_text.lines()[j].segments[0].char_range); 2358 render_text.lines()[j].segments[0].char_range);
2362 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, 2359 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2363 render_text.lines()[j].size.width()); 2360 render_text.lines()[j].size.width());
2364 } 2361 }
2365 } 2362 }
2366 } 2363 }
2367 2364
2365 TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) {
2366 const int kGlyphSize = 5;
2367 const struct {
2368 const wchar_t* const text;
2369 const WordWrapBehavior behavior;
2370 const size_t num_lines;
msw 2015/05/27 17:38:00 nit: Why not just assume 3 in the code; we assume
xdai1 2015/06/01 16:51:16 Done.
2371 const Range char_ranges[3];
2372 } kTestScenarios[] = {
2373 { L"a single run", IGNORE_LONG_WORDS, 3u,
2374 {Range(0, 2), Range(2, 9), Range(9, 12) } },
2375 // 3 words: "That's ", ""good". ", "aaa" and 7 runs: "That", "'", "s ",
2376 // """, "good", "". ", "aaa". They all mixed together.
2377 { L"That's \"good\". aaa", IGNORE_LONG_WORDS, 3u,
2378 {Range(0, 7), Range(7, 15), Range(15, 18) } },
2379 // Test "\"" should be put into a new line correctly.
2380 { L"a \"good\" one.", IGNORE_LONG_WORDS, 3u,
2381 {Range(0, 2), Range(2, 9), Range(9, 13) } },
2382 // Test for full-width space.
2383 { L"That's\x3000good.\x3000yyy", IGNORE_LONG_WORDS, 3u,
2384 {Range(0, 7), Range(7, 13), Range(13, 16) } },
2385 { L"a single run", TRUNCATE_LONG_WORDS, 3u,
2386 {Range(0, 2), Range(2, 6), Range(9, 12) } },
2387 { L"That's \"good\". aaa", TRUNCATE_LONG_WORDS, 3u,
2388 {Range(0, 4), Range(7, 11), Range(15, 18) } },
2389 { L"That's good. aaa", TRUNCATE_LONG_WORDS, 3u,
2390 {Range(0, 4), Range(7, 11), Range(13, 16) } },
2391 { L"a \"good\" one.", TRUNCATE_LONG_WORDS, 3u,
2392 {Range(0, 2), Range(2, 6), Range(9, 13) } },
2393 { L"asingleword", WRAP_LONG_WORDS, 3u,
2394 {Range(0, 4), Range(4, 8), Range(8, 11) } },
2395 { L"That's good", WRAP_LONG_WORDS, 3u,
2396 {Range(0, 4), Range(4, 7), Range(7, 11) } },
2397 { L"That's \"g\".", WRAP_LONG_WORDS, 3u,
2398 {Range(0, 4), Range(4, 7), Range(7, 11) } },
2399 };
2400
2401 RenderTextHarfBuzz render_text;
2402 render_text.SetMultiline(true);
2403 render_text.set_glyph_width_for_test(kGlyphSize);
2404 render_text.SetDisplayRect(Rect(0, 0, kGlyphSize * 4, 0));
2405
2406 Canvas canvas;
2407
2408 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) {
2409 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2410 render_text.SetText(WideToUTF16(kTestScenarios[i].text));
2411 render_text.SetWordWrapBehavior(kTestScenarios[i].behavior);
2412 render_text.Draw(&canvas);
2413
2414 ASSERT_EQ(kTestScenarios[i].num_lines, render_text.lines().size());
2415 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2416 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2417 // Merges all the segments ranges in the same line.
msw 2015/05/27 17:38:00 nit: "Merge"
xdai1 2015/06/01 16:51:16 Done.
2418 size_t segment_size = render_text.lines()[j].segments.size();
2419 Range line_range;
2420 if (segment_size > 0)
2421 line_range = Range(
2422 render_text.lines()[j].segments[0].char_range.start(),
2423 render_text.lines()[j].segments[segment_size - 1].char_range.end());
2424 EXPECT_EQ(kTestScenarios[i].char_ranges[j], line_range);
2425 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2426 render_text.lines()[j].size.width());
2427 }
2428 }
2429 }
2430
2368 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { 2431 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
2369 const wchar_t* kTestStrings[] = { 2432 const wchar_t* kTestStrings[] = {
2370 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", 2433 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n",
2371 }; 2434 };
2372 2435
2373 RenderTextHarfBuzz render_text; 2436 RenderTextHarfBuzz render_text;
2374 render_text.SetDisplayRect(Rect(200, 1000)); 2437 render_text.SetDisplayRect(Rect(200, 1000));
2375 Canvas canvas; 2438 Canvas canvas;
2376 2439
2377 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2440 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 render_text.EnsureLayout(); 2666 render_text.EnsureLayout();
2604 internal::TextRunList* run_list = render_text.GetRunList(); 2667 internal::TextRunList* run_list = render_text.GetRunList();
2605 ASSERT_EQ(3U, run_list->size()); 2668 ASSERT_EQ(3U, run_list->size());
2606 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); 2669 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
2607 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); 2670 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
2608 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); 2671 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
2609 2672
2610 render_text.SetText(WideToUTF16(L"x \x25B6 y")); 2673 render_text.SetText(WideToUTF16(L"x \x25B6 y"));
2611 render_text.EnsureLayout(); 2674 render_text.EnsureLayout();
2612 run_list = render_text.GetRunList(); 2675 run_list = render_text.GetRunList();
2613 ASSERT_EQ(3U, run_list->size()); 2676 ASSERT_EQ(4U, run_list->size());
2614 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); 2677 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
2615 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); 2678 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
2616 EXPECT_EQ(Range(3, 5), run_list->runs()[2]->range); 2679 EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
2680 EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
2617 } 2681 }
2618 2682
2619 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { 2683 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) {
2620 RenderTextHarfBuzz render_text; 2684 RenderTextHarfBuzz render_text;
2621 2685
2622 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is 2686 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is
2623 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be 2687 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be
2624 // separated. See crbug.com/448909 2688 // separated. See crbug.com/448909
2625 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); 2689 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
2626 render_text.EnsureLayout(); 2690 render_text.EnsureLayout();
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 string_size.set_width(string_size.width() / 2); 3005 string_size.set_width(string_size.width() / 2);
2942 render_text.SetDisplayRect(gfx::Rect(string_size)); 3006 render_text.SetDisplayRect(gfx::Rect(string_size));
2943 render_text.EnsureLayout(); 3007 render_text.EnsureLayout();
2944 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); 3008 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_);
2945 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); 3009 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count));
2946 EXPECT_NE(0, glyph_count); 3010 EXPECT_NE(0, glyph_count);
2947 } 3011 }
2948 #endif 3012 #endif
2949 3013
2950 } // namespace gfx 3014 } // 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