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

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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 93 // Test utility for Multiline_Newline test case. Empty |expected_range| means
94 // the blank line which has no segments. Otherwise |segments| should contain 94 // the blank line which has no segments. Otherwise |segment|'s range should
95 // exactly one line segment whose range equals to |expected_range|. 95 // equal to |expected_range|.
96 void VerifyLineSegments(const Range& expected_range, 96 void VerifyLineSegments(const Range& expected_range,
97 const std::vector<internal::LineSegment>& segments) { 97 const internal::LineSegment& segment) {
98 EXPECT_EQ(expected_range.is_empty() ? 0ul : 1ul, segments.size());
99 if (!expected_range.is_empty()) 98 if (!expected_range.is_empty())
100 EXPECT_EQ(expected_range, segments[0].char_range); 99 EXPECT_EQ(expected_range, segment.char_range);
101 } 100 }
102 101
103 // The class which records the drawing operations so that the test case can 102 // The class which records the drawing operations so that the test case can
104 // verify where exactly the glyphs are drawn. 103 // verify where exactly the glyphs are drawn.
105 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { 104 class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
106 public: 105 public:
107 struct TextLog { 106 struct TextLog {
108 TextLog() : glyph_count(0u) {} 107 TextLog() : glyph_count(0u) {}
109 PointF origin; 108 PointF origin;
110 size_t glyph_count; 109 size_t glyph_count;
(...skipping 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after
2121 const wchar_t* const text; 2120 const wchar_t* const text;
2122 const Range first_line_char_range; 2121 const Range first_line_char_range;
2123 const Range second_line_char_range; 2122 const Range second_line_char_range;
2124 bool is_ltr; 2123 bool is_ltr;
2125 } kTestStrings[] = { 2124 } kTestStrings[] = {
2126 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, 2125 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true },
2127 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, 2126 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true },
2128 { L"\x0627\x0644\x0644\x063A\x0629 " 2127 { L"\x0627\x0644\x0644\x063A\x0629 "
2129 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", 2128 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
2130 Range(0, 6), Range(6, 13), false }, 2129 Range(0, 6), Range(6, 13), false },
2131 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" 2130 { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
2132 L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } 2131 L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false }
2133 }; 2132 };
2134 2133
2135 RenderTextHarfBuzz render_text; 2134 RenderTextHarfBuzz render_text;
2136 // Specify the fixed width for characters to suppress the possible variations 2135 // Specify the fixed width for characters to suppress the possible variations
2137 // of linebreak results. 2136 // of linebreak results.
2138 render_text.set_glyph_width_for_test(5); 2137 render_text.set_glyph_width_for_test(5);
2139 render_text.SetDisplayRect(Rect(50, 1000)); 2138 render_text.SetDisplayRect(Rect(50, 1000));
2140 render_text.SetMultiline(true); 2139 render_text.SetMultiline(true);
2141 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); 2140 render_text.SetWordWrapBehavior(WRAP_LONG_WORDS);
2142 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); 2141 render_text.SetHorizontalAlignment(ALIGN_TO_HEAD);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 } 2199 }
2201 2200
2202 TEST_F(RenderTextTest, Multiline_Newline) { 2201 TEST_F(RenderTextTest, Multiline_Newline) {
2203 const struct { 2202 const struct {
2204 const wchar_t* const text; 2203 const wchar_t* const text;
2205 const size_t lines_count; 2204 const size_t lines_count;
2206 // Ranges of the characters on each line preceding the newline. 2205 // Ranges of the characters on each line preceding the newline.
2207 const Range line_char_ranges[3]; 2206 const Range line_char_ranges[3];
2208 } kTestStrings[] = { 2207 } kTestStrings[] = {
2209 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } }, 2208 {L"abc\ndef", 2ul, { Range(0, 3), Range(4, 7), Range::InvalidRange() } },
2210 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 6), Range::InvalidRange() } }, 2209 {L"a \n b ", 2ul, { Range(0, 2), Range(3, 4), Range(4, 6) } },
2211 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } }, 2210 {L"ab\n", 2ul, { Range(0, 2), Range(), Range::InvalidRange() } },
2212 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } }, 2211 {L"a\n\nb", 3ul, { Range(0, 1), Range(), Range(3, 4) } },
2213 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } }, 2212 {L"\nab", 2ul, { Range(), Range(1, 3), Range::InvalidRange() } },
2214 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } }, 2213 {L"\n", 2ul, { Range(), Range(), Range::InvalidRange() } },
2215 }; 2214 };
2216 2215
2217 RenderTextHarfBuzz render_text; 2216 RenderTextHarfBuzz render_text;
2218 render_text.SetDisplayRect(Rect(200, 1000)); 2217 render_text.SetDisplayRect(Rect(200, 1000));
2219 render_text.SetMultiline(true); 2218 render_text.SetMultiline(true);
2220 Canvas canvas; 2219 Canvas canvas;
2221 2220
2222 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2221 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2223 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 2222 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2224 render_text.SetText(WideToUTF16(kTestStrings[i].text)); 2223 render_text.SetText(WideToUTF16(kTestStrings[i].text));
2225 render_text.Draw(&canvas); 2224 render_text.Draw(&canvas);
2226 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); 2225 EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size());
2227 if (kTestStrings[i].lines_count != render_text.lines_.size()) 2226 if (kTestStrings[i].lines_count != render_text.lines_.size())
2228 continue; 2227 continue;
2229 2228
2230 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { 2229 for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) {
2231 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); 2230 SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j));
2232 VerifyLineSegments(kTestStrings[i].line_char_ranges[j], 2231 // There might be multiple segments in one line.
2233 render_text.lines_[j].segments); 2232 for (size_t k = 0; k < render_text.lines_[j].segments.size(); ++k) {
2233 VerifyLineSegments(kTestStrings[i].line_char_ranges[j + k],
2234 render_text.lines_[j].segments[k]);
2235 }
2234 } 2236 }
2235 } 2237 }
2236 } 2238 }
2237 2239
2238 // Make sure that multiline mode ignores elide behavior. 2240 // Make sure that multiline mode ignores elide behavior.
2239 TEST_F(RenderTextTest, Multiline_IgnoreElide) { 2241 TEST_F(RenderTextTest, Multiline_IgnoreElide) {
2240 const wchar_t kTestString[] = 2242 const wchar_t kTestString[] =
2241 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx"; 2243 L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx";
2242 const wchar_t kEllipsis[] = L"\x2026"; 2244 const wchar_t kEllipsis[] = L"\x2026";
2243 2245
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2358 for (size_t j = 0; j < render_text.lines().size(); ++j) { 2360 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2359 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); 2361 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2360 EXPECT_EQ(kTestScenarios[i].char_ranges[j], 2362 EXPECT_EQ(kTestScenarios[i].char_ranges[j],
2361 render_text.lines()[j].segments[0].char_range); 2363 render_text.lines()[j].segments[0].char_range);
2362 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, 2364 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2363 render_text.lines()[j].size.width()); 2365 render_text.lines()[j].size.width());
2364 } 2366 }
2365 } 2367 }
2366 } 2368 }
2367 2369
2370 TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) {
2371 const int kGlyphSize = 5;
2372 const struct {
2373 const wchar_t* const text;
2374 const size_t num_lines;
2375 const Range char_ranges[3];
2376 } kTestScenarios[] = {
2377 { L"That's good. aaa", 3u,
2378 {Range(0, 7), Range(7, 13), Range(13, 16) } },
2379 { L"That's \"good\". aaa", 3u,
2380 {Range(0, 7), Range(7, 15), Range(15, 18) } },
2381 // Test for full-width space.
2382 { L"That's\x3000good.\x3000yyy", 3u,
2383 {Range(0, 7), Range(7, 13), Range(13, 16) } }
2384 };
2385
2386 RenderTextHarfBuzz render_text;
2387 render_text.SetMultiline(true);
2388 render_text.set_glyph_width_for_test(kGlyphSize);
2389 render_text.SetDisplayRect(Rect(0, 0, kGlyphSize * 4, 0));
2390 render_text.SetWordWrapBehavior(IGNORE_LONG_WORDS);
2391
2392 Canvas canvas;
2393
2394 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) {
2395 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2396 render_text.SetText(WideToUTF16(kTestScenarios[i].text));
2397 render_text.Draw(&canvas);
2398
2399 ASSERT_EQ(kTestScenarios[i].num_lines, render_text.lines().size());
2400 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2401 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2402 // Merges all the segments ranges in the same line.
2403 size_t segment_size = render_text.lines()[j].segments.size();
2404 Range line_range(
2405 render_text.lines()[j].segments[0].char_range.start(),
2406 render_text.lines()[j].segments[segment_size - 1].char_range.end());
2407 EXPECT_EQ(kTestScenarios[i].char_ranges[j], line_range);
2408 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2409 render_text.lines()[j].size.width());
2410 }
2411 }
2412 }
2413
2368 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { 2414 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
2369 const wchar_t* kTestStrings[] = { 2415 const wchar_t* kTestStrings[] = {
2370 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", 2416 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n",
2371 }; 2417 };
2372 2418
2373 RenderTextHarfBuzz render_text; 2419 RenderTextHarfBuzz render_text;
2374 render_text.SetDisplayRect(Rect(200, 1000)); 2420 render_text.SetDisplayRect(Rect(200, 1000));
2375 Canvas canvas; 2421 Canvas canvas;
2376 2422
2377 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2423 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(); 2649 render_text.EnsureLayout();
2604 internal::TextRunList* run_list = render_text.GetRunList(); 2650 internal::TextRunList* run_list = render_text.GetRunList();
2605 ASSERT_EQ(3U, run_list->size()); 2651 ASSERT_EQ(3U, run_list->size());
2606 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); 2652 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
2607 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); 2653 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
2608 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); 2654 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
2609 2655
2610 render_text.SetText(WideToUTF16(L"x \x25B6 y")); 2656 render_text.SetText(WideToUTF16(L"x \x25B6 y"));
2611 render_text.EnsureLayout(); 2657 render_text.EnsureLayout();
2612 run_list = render_text.GetRunList(); 2658 run_list = render_text.GetRunList();
2613 ASSERT_EQ(3U, run_list->size()); 2659 ASSERT_EQ(4U, run_list->size());
2614 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); 2660 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
2615 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); 2661 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
2616 EXPECT_EQ(Range(3, 5), run_list->runs()[2]->range); 2662 EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
2663 EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
2617 } 2664 }
2618 2665
2619 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { 2666 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) {
2620 RenderTextHarfBuzz render_text; 2667 RenderTextHarfBuzz render_text;
2621 2668
2622 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is 2669 // \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 2670 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be
2624 // separated. See crbug.com/448909 2671 // separated. See crbug.com/448909
2625 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); 2672 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
2626 render_text.EnsureLayout(); 2673 render_text.EnsureLayout();
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 string_size.set_width(string_size.width() / 2); 2990 string_size.set_width(string_size.width() / 2);
2944 render_text.SetDisplayRect(gfx::Rect(string_size)); 2991 render_text.SetDisplayRect(gfx::Rect(string_size));
2945 render_text.EnsureLayout(); 2992 render_text.EnsureLayout();
2946 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); 2993 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_);
2947 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); 2994 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count));
2948 EXPECT_NE(0, glyph_count); 2995 EXPECT_NE(0, glyph_count);
2949 } 2996 }
2950 #endif 2997 #endif
2951 2998
2952 } // namespace gfx 2999 } // 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