| 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" | 
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" | 
| 12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" | 
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" | 
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" | 
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" | 
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" | 
| 17 #include "third_party/skia/include/core/SkSurface.h" | 17 #include "third_party/skia/include/core/SkSurface.h" | 
| 18 #include "ui/gfx/break_list.h" | 18 #include "ui/gfx/break_list.h" | 
| 19 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" | 
| 20 #include "ui/gfx/color_utils.h" | 20 #include "ui/gfx/color_utils.h" | 
| 21 #include "ui/gfx/font.h" | 21 #include "ui/gfx/font.h" | 
| 22 #include "ui/gfx/range/range.h" | 22 #include "ui/gfx/range/range.h" | 
| 23 #include "ui/gfx/range/range_f.h" | 23 #include "ui/gfx/range/range_f.h" | 
| 24 #include "ui/gfx/render_text_harfbuzz.h" | 24 #include "ui/gfx/render_text_harfbuzz.h" | 
|  | 25 #include "ui/gfx/text_utils.h" | 
| 25 | 26 | 
| 26 #if defined(OS_WIN) | 27 #if defined(OS_WIN) | 
| 27 #include "base/win/windows_version.h" | 28 #include "base/win/windows_version.h" | 
| 28 #include "ui/gfx/platform_font_win.h" | 29 #include "ui/gfx/platform_font_win.h" | 
| 29 #endif | 30 #endif | 
| 30 | 31 | 
| 31 #if defined(OS_MACOSX) | 32 #if defined(OS_MACOSX) | 
| 32 #include <ApplicationServices/ApplicationServices.h> | 33 #include <ApplicationServices/ApplicationServices.h> | 
| 33 | 34 | 
| 34 #include "ui/gfx/render_text_mac.h" | 35 #include "ui/gfx/render_text_mac.h" | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 83     render_text->MoveCursor(CHARACTER_BREAK, direction, false); | 84     render_text->MoveCursor(CHARACTER_BREAK, direction, false); | 
| 84   } | 85   } | 
| 85   // Check that cursoring is clamped at the line edge. | 86   // Check that cursoring is clamped at the line edge. | 
| 86   EXPECT_EQ(expected.back(), render_text->selection_model()); | 87   EXPECT_EQ(expected.back(), render_text->selection_model()); | 
| 87   // Check that it is the line edge. | 88   // Check that it is the line edge. | 
| 88   render_text->MoveCursor(LINE_BREAK, direction, false); | 89   render_text->MoveCursor(LINE_BREAK, direction, false); | 
| 89   EXPECT_EQ(expected.back(), render_text->selection_model()); | 90   EXPECT_EQ(expected.back(), render_text->selection_model()); | 
| 90 } | 91 } | 
| 91 #endif  // !defined(OS_MACOSX) | 92 #endif  // !defined(OS_MACOSX) | 
| 92 | 93 | 
| 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 | 94 // The class which records the drawing operations so that the test case can | 
| 104 // verify where exactly the glyphs are drawn. | 95 // verify where exactly the glyphs are drawn. | 
| 105 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { | 96 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { | 
| 106  public: | 97  public: | 
| 107   struct TextLog { | 98   struct TextLog { | 
| 108     TextLog() : glyph_count(0u) {} | 99     TextLog() : glyph_count(0u) {} | 
| 109     PointF origin; | 100     PointF origin; | 
| 110     size_t glyph_count; | 101     size_t glyph_count; | 
| 111   }; | 102   }; | 
| 112 | 103 | 
| (...skipping 2008 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2121     const wchar_t* const text; | 2112     const wchar_t* const text; | 
| 2122     const Range first_line_char_range; | 2113     const Range first_line_char_range; | 
| 2123     const Range second_line_char_range; | 2114     const Range second_line_char_range; | 
| 2124     bool is_ltr; | 2115     bool is_ltr; | 
| 2125   } kTestStrings[] = { | 2116   } kTestStrings[] = { | 
| 2126     { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, | 2117     { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, | 
| 2127     { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, | 2118     { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, | 
| 2128     { L"\x0627\x0644\x0644\x063A\x0629 " | 2119     { L"\x0627\x0644\x0644\x063A\x0629 " | 
| 2129       L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", | 2120       L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", | 
| 2130       Range(0, 6), Range(6, 13), false }, | 2121       Range(0, 6), Range(6, 13), false }, | 
| 2131     { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9" | 2122     { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9" | 
| 2132       L"\x05DA\x05DB\x05DD", Range(0, 4), Range(4, 12), false } | 2123       L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false } | 
| 2133   }; | 2124   }; | 
| 2134 | 2125 | 
| 2135   RenderTextHarfBuzz render_text; | 2126   RenderTextHarfBuzz render_text; | 
| 2136   // Specify the fixed width for characters to suppress the possible variations | 2127   // Specify the fixed width for characters to suppress the possible variations | 
| 2137   // of linebreak results. | 2128   // of linebreak results. | 
| 2138   render_text.set_glyph_width_for_test(5); | 2129   render_text.set_glyph_width_for_test(5); | 
| 2139   render_text.SetDisplayRect(Rect(50, 1000)); | 2130   render_text.SetDisplayRect(Rect(50, 1000)); | 
| 2140   render_text.SetMultiline(true); | 2131   render_text.SetMultiline(true); | 
| 2141   render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); | 2132   render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); | 
| 2142   render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); | 2133   render_text.SetHorizontalAlignment(ALIGN_TO_HEAD); | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2222   for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2213   for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 
| 2223     SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 2214     SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 
| 2224     render_text.SetText(WideToUTF16(kTestStrings[i].text)); | 2215     render_text.SetText(WideToUTF16(kTestStrings[i].text)); | 
| 2225     render_text.Draw(&canvas); | 2216     render_text.Draw(&canvas); | 
| 2226     EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); | 2217     EXPECT_EQ(kTestStrings[i].lines_count, render_text.lines_.size()); | 
| 2227     if (kTestStrings[i].lines_count != render_text.lines_.size()) | 2218     if (kTestStrings[i].lines_count != render_text.lines_.size()) | 
| 2228       continue; | 2219       continue; | 
| 2229 | 2220 | 
| 2230     for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { | 2221     for (size_t j = 0; j < kTestStrings[i].lines_count; ++j) { | 
| 2231       SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); | 2222       SCOPED_TRACE(base::StringPrintf("Line %" PRIuS "", j)); | 
| 2232       VerifyLineSegments(kTestStrings[i].line_char_ranges[j], | 2223       // There might be multiple segments in one line. Merge all the segments | 
| 2233                          render_text.lines_[j].segments); | 2224       // ranges in the same line. | 
|  | 2225       const size_t segment_size = render_text.lines()[j].segments.size(); | 
|  | 2226       Range line_range; | 
|  | 2227       if (segment_size > 0) | 
|  | 2228         line_range = Range( | 
|  | 2229             render_text.lines()[j].segments[0].char_range.start(), | 
|  | 2230             render_text.lines()[j].segments[segment_size - 1].char_range.end()); | 
|  | 2231       EXPECT_EQ(kTestStrings[i].line_char_ranges[j], line_range); | 
| 2234     } | 2232     } | 
| 2235   } | 2233   } | 
| 2236 } | 2234 } | 
| 2237 | 2235 | 
| 2238 // Make sure that multiline mode ignores elide behavior. | 2236 // Make sure that multiline mode ignores elide behavior. | 
| 2239 TEST_F(RenderTextTest, Multiline_IgnoreElide) { | 2237 TEST_F(RenderTextTest, Multiline_IgnoreElide) { | 
| 2240   const wchar_t kTestString[] = | 2238   const wchar_t kTestString[] = | 
| 2241       L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx"; | 2239       L"very very very long string xxxxxxxxxxxxxxxxxxxxxxxxxx"; | 
| 2242   const wchar_t kEllipsis[] = L"\x2026"; | 2240   const wchar_t kEllipsis[] = L"\x2026"; | 
| 2243 | 2241 | 
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2358     for (size_t j = 0; j < render_text.lines().size(); ++j) { | 2356     for (size_t j = 0; j < render_text.lines().size(); ++j) { | 
| 2359       SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); | 2357       SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); | 
| 2360       EXPECT_EQ(kTestScenarios[i].char_ranges[j], | 2358       EXPECT_EQ(kTestScenarios[i].char_ranges[j], | 
| 2361                 render_text.lines()[j].segments[0].char_range); | 2359                 render_text.lines()[j].segments[0].char_range); | 
| 2362       EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, | 2360       EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, | 
| 2363                 render_text.lines()[j].size.width()); | 2361                 render_text.lines()[j].size.width()); | 
| 2364     } | 2362     } | 
| 2365   } | 2363   } | 
| 2366 } | 2364 } | 
| 2367 | 2365 | 
|  | 2366 TEST_F(RenderTextTest, Multiline_LineBreakerBehavior) { | 
|  | 2367   const int kGlyphSize = 5; | 
|  | 2368   const struct { | 
|  | 2369     const wchar_t* const text; | 
|  | 2370     const WordWrapBehavior behavior; | 
|  | 2371     const Range char_ranges[3]; | 
|  | 2372   } kTestScenarios[] = { | 
|  | 2373       { L"a single run", IGNORE_LONG_WORDS, | 
|  | 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, | 
|  | 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, | 
|  | 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, | 
|  | 2384         {Range(0, 7), Range(7, 13), Range(13, 16) } }, | 
|  | 2385       { L"a single run", TRUNCATE_LONG_WORDS, | 
|  | 2386         {Range(0, 2), Range(2, 6), Range(9, 12) } }, | 
|  | 2387       { L"That's \"good\". aaa", TRUNCATE_LONG_WORDS, | 
|  | 2388         {Range(0, 4), Range(7, 11), Range(15, 18) } }, | 
|  | 2389       { L"That's good. aaa", TRUNCATE_LONG_WORDS, | 
|  | 2390         {Range(0, 4), Range(7, 11), Range(13, 16) } }, | 
|  | 2391       { L"a \"good\" one.", TRUNCATE_LONG_WORDS, | 
|  | 2392         {Range(0, 2), Range(2, 6), Range(9, 13) } }, | 
|  | 2393       { L"asingleword", WRAP_LONG_WORDS, | 
|  | 2394         {Range(0, 4), Range(4, 8), Range(8, 11) } }, | 
|  | 2395       { L"That's good", WRAP_LONG_WORDS, | 
|  | 2396         {Range(0, 4), Range(4, 7), Range(7, 11) } }, | 
|  | 2397       { L"That's \"g\".", WRAP_LONG_WORDS, | 
|  | 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(3u, 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       // Merge all the segments ranges in the same line. | 
|  | 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 | 
|  | 2431 // Test that Surrogate pairs or combining character sequences do not get | 
|  | 2432 // separated by line breaking. | 
|  | 2433 TEST_F(RenderTextTest, Multiline_SurrogatePairsOrCombiningChars) { | 
|  | 2434   RenderTextHarfBuzz render_text; | 
|  | 2435   render_text.SetMultiline(true); | 
|  | 2436   render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); | 
|  | 2437 | 
|  | 2438   // Below is 'MUSICAL SYMBOL G CLEF' (U+1D11E), which is represented in UTF-16 | 
|  | 2439   // as two code units forming a surrogate pair: 0xD834 0xDD1E. | 
|  | 2440   const base::char16 kSurrogate[] = {0xD834, 0xDD1E, 0}; | 
|  | 2441   const base::string16 text_surrogate(kSurrogate); | 
|  | 2442   const int kSurrogateWidth = | 
|  | 2443       GetStringWidth(kSurrogate, render_text.font_list()); | 
|  | 2444 | 
|  | 2445   // Below is a Devanagari two-character combining sequence U+0921 U+093F. The | 
|  | 2446   // sequence forms a single display character and should not be separated. | 
|  | 2447   const base::char16 kCombiningChars[] = {0x921, 0x93F, 0}; | 
|  | 2448   const base::string16 text_combining(kCombiningChars); | 
|  | 2449   const int kCombiningCharsWidth = | 
|  | 2450       GetStringWidth(kCombiningChars, render_text.font_list()); | 
|  | 2451 | 
|  | 2452   const struct { | 
|  | 2453     const base::string16 text; | 
|  | 2454     const int display_width; | 
|  | 2455     const Range char_ranges[3]; | 
|  | 2456   } kTestScenarios[] = { | 
|  | 2457       { text_surrogate + text_surrogate + text_surrogate, | 
|  | 2458         kSurrogateWidth / 2 * 3, | 
|  | 2459         { Range(0, 2), Range(2, 4),  Range(4, 6) } }, | 
|  | 2460       { text_surrogate + UTF8ToUTF16(" ") + kCombiningChars, | 
|  | 2461         std::min(kSurrogateWidth, kCombiningCharsWidth) / 2, | 
|  | 2462         { Range(0, 2), Range(2, 3), Range(3, 5) } }, | 
|  | 2463   }; | 
|  | 2464 | 
|  | 2465   Canvas canvas; | 
|  | 2466 | 
|  | 2467   for (size_t i = 0; i < arraysize(kTestScenarios); ++i) { | 
|  | 2468     SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 
|  | 2469     render_text.SetText(kTestScenarios[i].text); | 
|  | 2470     render_text.SetDisplayRect(Rect(0, 0, kTestScenarios[i].display_width, 0)); | 
|  | 2471     render_text.Draw(&canvas); | 
|  | 2472 | 
|  | 2473     ASSERT_EQ(3u, render_text.lines().size()); | 
|  | 2474     for (size_t j = 0; j < render_text.lines().size(); ++j) { | 
|  | 2475       SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); | 
|  | 2476       // There is only one segment in each line. | 
|  | 2477       EXPECT_EQ(kTestScenarios[i].char_ranges[j], | 
|  | 2478                 render_text.lines()[j].segments[0].char_range); | 
|  | 2479     } | 
|  | 2480   } | 
|  | 2481 } | 
|  | 2482 | 
|  | 2483 // Test that Zero width characters have the correct line breaking behavior. | 
|  | 2484 TEST_F(RenderTextTest, Multiline_ZeroWidthChars) { | 
|  | 2485   RenderTextHarfBuzz render_text; | 
|  | 2486   render_text.SetMultiline(true); | 
|  | 2487   render_text.SetWordWrapBehavior(WRAP_LONG_WORDS); | 
|  | 2488 | 
|  | 2489   const base::char16 kZeroWidthSpace = {0x200B}; | 
|  | 2490   const base::string16 text(UTF8ToUTF16("test") + kZeroWidthSpace + | 
|  | 2491                             UTF8ToUTF16("\n") + kZeroWidthSpace + | 
|  | 2492                             UTF8ToUTF16("test.")); | 
|  | 2493   const int kTestWidth = | 
|  | 2494       GetStringWidth(UTF8ToUTF16("test"), render_text.font_list()); | 
|  | 2495   const Range char_ranges[3] = {Range(0, 5), Range(6, 11), Range(11, 12)}; | 
|  | 2496 | 
|  | 2497   Canvas canvas; | 
|  | 2498   render_text.SetText(text); | 
|  | 2499   render_text.SetDisplayRect(Rect(0, 0, kTestWidth, 0)); | 
|  | 2500   render_text.Draw(&canvas); | 
|  | 2501 | 
|  | 2502   ASSERT_EQ(3u, render_text.lines().size()); | 
|  | 2503   for (size_t j = 0; j < render_text.lines().size(); ++j) { | 
|  | 2504     SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); | 
|  | 2505     int segment_size = render_text.lines()[j].segments.size(); | 
|  | 2506     ASSERT_GT(segment_size, 0); | 
|  | 2507     Range line_range( | 
|  | 2508         render_text.lines()[j].segments[0].char_range.start(), | 
|  | 2509         render_text.lines()[j].segments[segment_size - 1].char_range.end()); | 
|  | 2510     EXPECT_EQ(char_ranges[j], line_range); | 
|  | 2511   } | 
|  | 2512 } | 
|  | 2513 | 
| 2368 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { | 2514 TEST_F(RenderTextTest, NewlineWithoutMultilineFlag) { | 
| 2369   const wchar_t* kTestStrings[] = { | 2515   const wchar_t* kTestStrings[] = { | 
| 2370     L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", | 2516     L"abc\ndef", L"a \n b ", L"ab\n", L"a\n\nb", L"\nab", L"\n", | 
| 2371   }; | 2517   }; | 
| 2372 | 2518 | 
| 2373   RenderTextHarfBuzz render_text; | 2519   RenderTextHarfBuzz render_text; | 
| 2374   render_text.SetDisplayRect(Rect(200, 1000)); | 2520   render_text.SetDisplayRect(Rect(200, 1000)); | 
| 2375   Canvas canvas; | 2521   Canvas canvas; | 
| 2376 | 2522 | 
| 2377   for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2523   for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2603   render_text.EnsureLayout(); | 2749   render_text.EnsureLayout(); | 
| 2604   internal::TextRunList* run_list = render_text.GetRunList(); | 2750   internal::TextRunList* run_list = render_text.GetRunList(); | 
| 2605   ASSERT_EQ(3U, run_list->size()); | 2751   ASSERT_EQ(3U, run_list->size()); | 
| 2606   EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); | 2752   EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); | 
| 2607   EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); | 2753   EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); | 
| 2608   EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); | 2754   EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); | 
| 2609 | 2755 | 
| 2610   render_text.SetText(WideToUTF16(L"x \x25B6 y")); | 2756   render_text.SetText(WideToUTF16(L"x \x25B6 y")); | 
| 2611   render_text.EnsureLayout(); | 2757   render_text.EnsureLayout(); | 
| 2612   run_list = render_text.GetRunList(); | 2758   run_list = render_text.GetRunList(); | 
| 2613   ASSERT_EQ(3U, run_list->size()); | 2759   ASSERT_EQ(4U, run_list->size()); | 
| 2614   EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); | 2760   EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); | 
| 2615   EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); | 2761   EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); | 
| 2616   EXPECT_EQ(Range(3, 5), run_list->runs()[2]->range); | 2762   EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range); | 
|  | 2763   EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range); | 
| 2617 } | 2764 } | 
| 2618 | 2765 | 
| 2619 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { | 2766 TEST_F(RenderTextTest, HarfBuzz_BreakRunsByEmoji) { | 
| 2620   RenderTextHarfBuzz render_text; | 2767   RenderTextHarfBuzz render_text; | 
| 2621 | 2768 | 
| 2622   // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is | 2769   // \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 | 2770   // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be | 
| 2624   // separated. See crbug.com/448909 | 2771   // separated. See crbug.com/448909 | 
| 2625   render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); | 2772   render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); | 
| 2626   render_text.EnsureLayout(); | 2773   render_text.EnsureLayout(); | 
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2941   string_size.set_width(string_size.width() / 2); | 3088   string_size.set_width(string_size.width() / 2); | 
| 2942   render_text.SetDisplayRect(gfx::Rect(string_size)); | 3089   render_text.SetDisplayRect(gfx::Rect(string_size)); | 
| 2943   render_text.EnsureLayout(); | 3090   render_text.EnsureLayout(); | 
| 2944   CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); | 3091   CFIndex glyph_count = CTLineGetGlyphCount(render_text.line_); | 
| 2945   EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); | 3092   EXPECT_GT(text.size(), static_cast<size_t>(glyph_count)); | 
| 2946   EXPECT_NE(0, glyph_count); | 3093   EXPECT_NE(0, glyph_count); | 
| 2947 } | 3094 } | 
| 2948 #endif | 3095 #endif | 
| 2949 | 3096 | 
| 2950 }  // namespace gfx | 3097 }  // namespace gfx | 
| OLD | NEW | 
|---|