| OLD | NEW | 
|---|
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|