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

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: Rebase 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 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 };
2382
2383 RenderTextHarfBuzz render_text;
2384 render_text.SetMultiline(true);
2385 render_text.set_glyph_width_for_test(kGlyphSize);
2386 render_text.SetDisplayRect(Rect(0, 0, kGlyphSize * 4, 0));
2387 render_text.SetWordWrapBehavior(IGNORE_LONG_WORDS);
2388
2389 Canvas canvas;
2390
2391 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) {
2392 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2393 render_text.SetText(WideToUTF16(kTestScenarios[i].text));
2394 render_text.Draw(&canvas);
2395
2396 ASSERT_EQ(kTestScenarios[i].num_lines, render_text.lines().size());
2397 for (size_t j = 0; j < render_text.lines().size(); ++j) {
2398 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
2399 // Merges all the segments ranges in the same line.
2400 size_t segment_size = render_text.lines()[j].segments.size();
2401 Range line_range(
2402 render_text.lines()[j].segments[0].char_range.start(),
2403 render_text.lines()[j].segments[segment_size - 1].char_range.end());
2404 EXPECT_EQ(kTestScenarios[i].char_ranges[j], line_range);
2405 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
2406 render_text.lines()[j].size.width());
2407 }
2408 }
2409 }
2410
2368 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { 2411 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) {
2369 const wchar_t* kTestStrings[] = { 2412 const wchar_t* kTestStrings[] = {
2370 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", 2413 L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n",
2371 }; 2414 };
2372 2415
2373 RenderTextHarfBuzz render_text; 2416 RenderTextHarfBuzz render_text;
2374 render_text.SetDisplayRect(Rect(200, 1000)); 2417 render_text.SetDisplayRect(Rect(200, 1000));
2375 Canvas canvas; 2418 Canvas canvas;
2376 2419
2377 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 2420 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(); 2646 render_text.EnsureLayout();
2604 internal::TextRunList* run_list = render_text.GetRunList(); 2647 internal::TextRunList* run_list = render_text.GetRunList();
2605 ASSERT_EQ(3U, run_list->size()); 2648 ASSERT_EQ(3U, run_list->size());
2606 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); 2649 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
2607 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); 2650 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
2608 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); 2651 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
2609 2652
2610 render_text.SetText(WideToUTF16(L"x \x25B6 y")); 2653 render_text.SetText(WideToUTF16(L"x \x25B6 y"));
2611 render_text.EnsureLayout(); 2654 render_text.EnsureLayout();
2612 run_list = render_text.GetRunList(); 2655 run_list = render_text.GetRunList();
2613 ASSERT_EQ(3U, run_list->size()); 2656 ASSERT_EQ(4U, run_list->size());
2614 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); 2657 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
2615 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); 2658 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
2616 EXPECT_EQ(Range(3, 5), run_list->runs()[2]->range); 2659 EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
2660 EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
2617 } 2661 }
2618 2662
2619 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { 2663 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) {
2620 RenderTextHarfBuzz render_text; 2664 RenderTextHarfBuzz render_text;
2621 2665
2622 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is 2666 // \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 2667 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be
2624 // separated. See crbug.com/448909 2668 // separated. See crbug.com/448909
2625 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); 2669 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
2626 render_text.EnsureLayout(); 2670 render_text.EnsureLayout();
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 string_size.set_width(string_size.width() / 2); 2987 string_size.set_width(string_size.width() / 2);
2944 render_text.SetDisplayRect(gfx::Rect(string_size)); 2988 render_text.SetDisplayRect(gfx::Rect(string_size));
2945 render_text.EnsureLayout(); 2989 render_text.EnsureLayout();
2946 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); 2990 CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_);
2947 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); 2991 EXPECT_GT(text.size(), static_cast<size_t>(glyph_count));
2948 EXPECT_NE(0, glyph_count); 2992 EXPECT_NE(0, glyph_count);
2949 } 2993 }
2950 #endif 2994 #endif
2951 2995
2952 } // namespace gfx 2996 } // 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