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

Side by Side Diff: ui/gfx/render_text_unittest.cc

Issue 2942843002: RenderText: always break runs at whitespace (Closed)
Patch Set: Fix 10.9 Created 3 years, 6 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
« no previous file with comments | « ui/gfx/render_text_harfbuzz.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <limits.h> 7 #include <limits.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 std::vector<base::char16> arr(length, RenderText::kPasswordReplacementChar); 298 std::vector<base::char16> arr(length, RenderText::kPasswordReplacementChar);
299 arr[reveal_index] = reveal_char; 299 arr[reveal_index] = reveal_char;
300 return base::string16(arr.begin(), arr.end()); 300 return base::string16(arr.begin(), arr.end());
301 } 301 }
302 302
303 // Helper method to return an obscured string of the given |length|. 303 // Helper method to return an obscured string of the given |length|.
304 base::string16 GetObscuredString(size_t length) { 304 base::string16 GetObscuredString(size_t length) {
305 return base::string16(length, RenderText::kPasswordReplacementChar); 305 return base::string16(length, RenderText::kPasswordReplacementChar);
306 } 306 }
307 307
308 std::vector<base::string16> ToString16Vec(
Alexei Svitkine (slow) 2017/06/16 14:45:33 Nit: Add 1-line comments for the new helper method
tapted 2017/06/19 04:10:50 Done.
309 const std::vector<const char*>& utf8_literals) {
310 std::vector<base::string16> vec;
311 for (auto* const literal : utf8_literals)
312 vec.push_back(UTF8ToUTF16(literal));
313 return vec;
314 }
315
316 Range LineCharRange(const internal::Line& line) {
317 if (line.segments.empty())
318 return Range();
319 Range ltr(line.segments.front().char_range.start(),
320 line.segments.back().char_range.end());
321 if (ltr.end() > ltr.start())
322 return ltr;
323
324 // For RTL, the order of segments is reversed, but the ranges are not.
325 return Range(line.segments.back().char_range.start(),
326 line.segments.front().char_range.end());
327 }
328
308 // The class which records the drawing operations so that the test case can 329 // The class which records the drawing operations so that the test case can
309 // verify where exactly the glyphs are drawn. 330 // verify where exactly the glyphs are drawn.
310 class TestSkiaTextRenderer : public internal::SkiaTextRenderer { 331 class TestSkiaTextRenderer : public internal::SkiaTextRenderer {
311 public: 332 public:
312 struct TextLog { 333 struct TextLog {
313 TextLog() : glyph_count(0u), color(SK_ColorTRANSPARENT) {} 334 TextLog() : glyph_count(0u), color(SK_ColorTRANSPARENT) {}
314 PointF origin; 335 PointF origin;
315 size_t glyph_count; 336 size_t glyph_count;
316 SkColor color; 337 SkColor color;
317 }; 338 };
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 return test::RenderTextTestApi::GetRendererPaint(renderer()); 476 return test::RenderTextTestApi::GetRendererPaint(renderer());
456 } 477 }
457 478
458 void DrawVisualText() { test_api_->DrawVisualText(renderer()); } 479 void DrawVisualText() { test_api_->DrawVisualText(renderer()); }
459 480
460 internal::TextRunList* GetHarfBuzzRunList() { 481 internal::TextRunList* GetHarfBuzzRunList() {
461 DCHECK_EQ(RENDER_TEXT_HARFBUZZ, GetParam()); 482 DCHECK_EQ(RENDER_TEXT_HARFBUZZ, GetParam());
462 return test_api_->GetHarfBuzzRunList(); 483 return test_api_->GetHarfBuzzRunList();
463 } 484 }
464 485
486 std::vector<base::string16> GetRuns() {
487 std::vector<base::string16> runs_as_text;
488 const std::vector<RenderText::FontSpan> spans =
489 render_text_->GetFontSpansForTesting();
490 for (const auto& span : spans) {
491 runs_as_text.push_back(render_text_->text().substr(span.second.GetMin(),
492 span.second.length()));
493 }
494 return runs_as_text;
495 }
496
497 std::vector<base::string16> RunsFor(const base::string16& text) {
498 render_text_->SetText(text);
499 test_api()->EnsureLayout();
500 return GetRuns();
501 }
502
465 void ResetRenderTextInstance() { 503 void ResetRenderTextInstance() {
466 render_text_ = CreateRenderTextInstance(); 504 render_text_ = CreateRenderTextInstance();
467 test_api_.reset(new test::RenderTextTestApi(GetRenderText())); 505 test_api_.reset(new test::RenderTextTestApi(GetRenderText()));
468 } 506 }
469 507
470 RenderText* GetRenderText() { return render_text_.get(); }; 508 RenderText* GetRenderText() { return render_text_.get(); };
471 509
472 RenderTextHarfBuzz* GetRenderTextHarfBuzz() { 510 RenderTextHarfBuzz* GetRenderTextHarfBuzz() {
473 DCHECK_EQ(RENDER_TEXT_HARFBUZZ, GetParam()); 511 DCHECK_EQ(RENDER_TEXT_HARFBUZZ, GetParam());
474 return static_cast<RenderTextHarfBuzz*>(GetRenderText()); 512 return static_cast<RenderTextHarfBuzz*>(GetRenderText());
(...skipping 2440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2915 render_text->SetText(WideToUTF16(kTestStrings[i])); 2953 render_text->SetText(WideToUTF16(kTestStrings[i]));
2916 const int expected_width = render_text->GetStringSize().width(); 2954 const int expected_width = render_text->GetStringSize().width();
2917 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); 2955 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD));
2918 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); 2956 EXPECT_EQ(expected_width, render_text->GetStringSize().width());
2919 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119 2957 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119
2920 render_text->Draw(canvas()); 2958 render_text->Draw(canvas());
2921 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); 2959 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
2922 } 2960 }
2923 } 2961 }
2924 2962
2963 // Test that characters commonly used in the context of several scripts do not
2964 // cause text runs to break. For example the Japanese "long sound symbol" --
2965 // normally only used in a Katakana script, is also used on occasion when in
2966 // Hiragana scripts. It shouldn't cause a Hiragana text run break since that
2967 // could upset kerning.
2968 TEST_P(RenderTextTest, ScriptExtensionsDoNotBreak) {
2969 // Apparently ramen restaurants prefer "らーめん" over "らあめん". The "dash"
2970 // is the long sound symbol and usually just appears in Katakana writing.
2971 const base::string16 ramen_hiragana = UTF8ToUTF16("らーめん");
2972 const base::string16 ramen_katakana = UTF8ToUTF16("ラーメン");
2973 const base::string16 ramen_mixed = UTF8ToUTF16("らあメン");
2974
2975 EXPECT_EQ(std::vector<base::string16>({ramen_hiragana}),
2976 RunsFor(ramen_hiragana));
2977 EXPECT_EQ(std::vector<base::string16>({ramen_katakana}),
2978 RunsFor(ramen_katakana));
2979
2980 // Currently Harfbuzz breaks this, but not Mac.
2981 if (GetParam() == RENDER_TEXT_HARFBUZZ)
2982 EXPECT_EQ(ToString16Vec({"らあ", "メン"}), RunsFor(ramen_mixed));
2983 else
2984 EXPECT_EQ(std::vector<base::string16>({ramen_mixed}), RunsFor(ramen_mixed));
2985 }
2986
2987 // Test that whitespace breaks runs of text. E.g. this can permit better fonts
2988 // to be chosen by the fallback mechanism when a font does not provide
2989 // whitespace glyphs for all scripts. See http://crbug.com/731563.
2990 TEST_P(RenderTextTest, WhitespaceDoesBreak) {
2991 // Title of the Wikipedia page for "bit". ASCII spaces. In Hebrew and English.
2992 // Note that the hyphens that Wikipedia uses are different. English uses
2993 // ASCII (U+002D) "hyphen minus", Hebrew uses the U+2013 "EN Dash".
2994 const base::string16 ascii_space_he = UTF8ToUTF16("סיבית – ויקיפדיה");
2995 const base::string16 ascii_space_en = ASCIIToUTF16("Bit - Wikipedia");
2996
2997 // This says "thank you very much" with a full-width non-ascii space (U+3000).
2998 const base::string16 full_width_space = UTF8ToUTF16("ども ありがと");
2999
3000 if (GetParam() == RENDER_TEXT_HARFBUZZ) {
3001 // Old behavior:
3002 // { "סיבית ", "–", " ", "ויקיפדיה"" }
3003 // { "Bit ", "- ", "Wikipedia" }
3004 // { "ども ありがと"" }.
3005 EXPECT_EQ(ToString16Vec({"סיבית", " ", "–", " ", "ויקיפדיה"}),
3006 RunsFor(ascii_space_he));
3007 EXPECT_EQ(ToString16Vec({"Bit", " - ", "Wikipedia"}),
3008 RunsFor(ascii_space_en));
3009 EXPECT_EQ(ToString16Vec({"ども", " ", "ありがと"}),
3010 RunsFor(full_width_space));
3011 } else {
3012 // Mac is a black box. From this it seems to draw RTL runs right to left and
3013 // is able to use typeface characteristics when breaking runs. On 10.9, the
3014 // Hebrew string is given a single run, and on 10.12 it's given 3 runs. It
3015 // doesn't really matter as far as the rest of the RenderText machinery is
3016 // concerned.
3017 auto actual = RunsFor(ascii_space_he);
3018 if (actual.size() == 3) {
3019 EXPECT_EQ(ToString16Vec({"ויקיפדיה", " – ", "סיבית"}), actual);
3020 } else {
3021 EXPECT_EQ(ToString16Vec({"סיבית – ויקיפדיה"}), actual);
3022 }
3023 EXPECT_EQ(ToString16Vec({"Bit - Wikipedia"}), RunsFor(ascii_space_en));
3024 EXPECT_EQ(ToString16Vec({"ども ありがと"}), RunsFor(full_width_space));
3025 }
3026 }
3027
2925 // Ensure strings wrap onto multiple lines for a small available width. 3028 // Ensure strings wrap onto multiple lines for a small available width.
2926 TEST_P(RenderTextHarfBuzzTest, Multiline_MinWidth) { 3029 TEST_P(RenderTextHarfBuzzTest, Multiline_MinWidth) {
2927 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, 3030 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl,
2928 kRtlLtr, kRtlLtrRtl }; 3031 kRtlLtr, kRtlLtrRtl };
2929 3032
2930 RenderText* render_text = GetRenderText(); 3033 RenderText* render_text = GetRenderText();
2931 render_text->SetDisplayRect(Rect(1, 1000)); 3034 render_text->SetDisplayRect(Rect(1, 1000));
2932 render_text->SetMultiline(true); 3035 render_text->SetMultiline(true);
2933 render_text->SetWordWrapBehavior(WRAP_LONG_WORDS); 3036 render_text->SetWordWrapBehavior(WRAP_LONG_WORDS);
2934 3037
2935 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 3038 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2936 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 3039 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2937 render_text->SetText(WideToUTF16(kTestStrings[i])); 3040 render_text->SetText(WideToUTF16(kTestStrings[i]));
2938 render_text->Draw(canvas()); 3041 render_text->Draw(canvas());
2939 EXPECT_GT(test_api()->lines().size(), 1U); 3042 EXPECT_GT(test_api()->lines().size(), 1U);
2940 } 3043 }
2941 } 3044 }
2942 3045
2943 // Ensure strings wrap onto multiple lines for a normal available width. 3046 // Ensure strings wrap onto multiple lines for a normal available width.
2944 TEST_P(RenderTextHarfBuzzTest, Multiline_NormalWidth) { 3047 TEST_P(RenderTextHarfBuzzTest, Multiline_NormalWidth) {
3048 // Should RenderText suppress drawing whitespace at the end of a line?
3049 // Currently it does not.
2945 const struct { 3050 const struct {
2946 const wchar_t* const text; 3051 const wchar_t* const text;
2947 const Range first_line_char_range; 3052 const Range first_line_char_range;
2948 const Range second_line_char_range; 3053 const Range second_line_char_range;
3054
3055 // Lengths of each text run. Runs break at whitespace.
3056 std::vector<size_t> run_lengths;
3057
3058 // The index of the text run that should start the second line.
3059 int second_line_run_index;
3060
2949 bool is_ltr; 3061 bool is_ltr;
2950 } kTestStrings[] = { 3062 } kTestStrings[] = {
2951 { L"abc defg hijkl", Range(0, 9), Range(9, 14), true }, 3063 {L"abc defg hijkl", Range(0, 9), Range(9, 14), {3, 1, 4, 1, 5}, 4, true},
2952 { L"qwertyzxcvbn", Range(0, 10), Range(10, 12), true }, 3064 {L"qwertyzxcvbn", Range(0, 10), Range(10, 12), {10, 2}, 1, true},
2953 { L"\x0627\x0644\x0644\x063A\x0629 " 3065 // RTL: should render left-to-right as "<space>43210 \n cba9876".
2954 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629", 3066 {L"\x0627\x0644\x0644\x063A\x0629 "
2955 Range(0, 6), Range(6, 13), false }, 3067 L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
2956 { L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9" 3068 Range(0, 6),
2957 L"\x05DA\x05DB\x05DD", Range(0, 5), Range(5, 13), false } 3069 Range(6, 13),
2958 }; 3070 {1 /* space first */, 5, 7},
3071 2,
3072 false},
3073 // RTL: should render left-to-right as "<space>3210 \n cba98765".
3074 {L"\x062A\x0641\x0627\x062D \x05EA\x05E4\x05D5\x05D6\x05D9"
3075 L"\x05DA\x05DB\x05DD",
3076 Range(0, 5),
3077 Range(5, 13),
3078 {1 /* space first */, 5, 8},
3079 2,
3080 false}};
2959 3081
2960 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz(); 3082 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
2961 3083
2962 // Specify the fixed width for characters to suppress the possible variations 3084 // Specify the fixed width for characters to suppress the possible variations
2963 // of linebreak results. 3085 // of linebreak results.
2964 SetGlyphWidth(5); 3086 SetGlyphWidth(5);
2965 render_text->SetDisplayRect(Rect(50, 1000)); 3087 render_text->SetDisplayRect(Rect(50, 1000));
2966 render_text->SetMultiline(true); 3088 render_text->SetMultiline(true);
2967 render_text->SetWordWrapBehavior(WRAP_LONG_WORDS); 3089 render_text->SetWordWrapBehavior(WRAP_LONG_WORDS);
2968 render_text->SetHorizontalAlignment(ALIGN_TO_HEAD); 3090 render_text->SetHorizontalAlignment(ALIGN_TO_HEAD);
2969 3091
2970 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { 3092 for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2971 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); 3093 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2972 render_text->SetText(WideToUTF16(kTestStrings[i].text)); 3094 render_text->SetText(WideToUTF16(kTestStrings[i].text));
2973 DrawVisualText(); 3095 DrawVisualText();
2974 3096
2975 ASSERT_EQ(2U, test_api()->lines().size()); 3097 ASSERT_EQ(2U, test_api()->lines().size());
2976 ASSERT_EQ(1U, test_api()->lines()[0].segments.size());
2977 EXPECT_EQ(kTestStrings[i].first_line_char_range, 3098 EXPECT_EQ(kTestStrings[i].first_line_char_range,
2978 test_api()->lines()[0].segments[0].char_range); 3099 LineCharRange(test_api()->lines()[0]));
2979 ASSERT_EQ(1U, test_api()->lines()[1].segments.size());
2980 EXPECT_EQ(kTestStrings[i].second_line_char_range, 3100 EXPECT_EQ(kTestStrings[i].second_line_char_range,
2981 test_api()->lines()[1].segments[0].char_range); 3101 LineCharRange(test_api()->lines()[1]));
2982 3102
2983 std::vector<TestSkiaTextRenderer::TextLog> text_log; 3103 std::vector<TestSkiaTextRenderer::TextLog> text_log;
2984 renderer()->GetTextLogAndReset(&text_log); 3104 renderer()->GetTextLogAndReset(&text_log);
2985 ASSERT_EQ(2U, text_log.size()); 3105
3106 ASSERT_EQ(kTestStrings[i].run_lengths.size(), text_log.size());
3107
2986 // NOTE: this expectation compares the character length and glyph counts, 3108 // NOTE: this expectation compares the character length and glyph counts,
2987 // which isn't always equal. This is okay only because all the test 3109 // which isn't always equal. This is okay only because all the test
2988 // strings are simple (like, no compound characters nor UTF16-surrogate 3110 // strings are simple (like, no compound characters nor UTF16-surrogate
2989 // pairs). Be careful in case more complicated test strings are added. 3111 // pairs). Be careful in case more complicated test strings are added.
2990 EXPECT_EQ(kTestStrings[i].first_line_char_range.length(), 3112 EXPECT_EQ(kTestStrings[i].run_lengths[0], text_log[0].glyph_count);
2991 text_log[0].glyph_count); 3113 const int second_line_start = kTestStrings[i].second_line_run_index;
2992 EXPECT_EQ(kTestStrings[i].second_line_char_range.length(), 3114 EXPECT_EQ(kTestStrings[i].run_lengths[second_line_start],
2993 text_log[1].glyph_count); 3115 text_log[second_line_start].glyph_count);
2994 EXPECT_LT(text_log[0].origin.y(), text_log[1].origin.y()); 3116 EXPECT_LT(text_log[0].origin.y(), text_log[second_line_start].origin.y());
2995 if (kTestStrings[i].is_ltr) { 3117 if (kTestStrings[i].is_ltr) {
2996 EXPECT_EQ(0, text_log[0].origin.x()); 3118 EXPECT_EQ(0, text_log[0].origin.x());
2997 EXPECT_EQ(0, text_log[1].origin.x()); 3119 EXPECT_EQ(0, text_log[second_line_start].origin.x());
2998 } else { 3120 } else {
2999 EXPECT_LT(0, text_log[0].origin.x()); 3121 EXPECT_LT(0, text_log[0].origin.x());
3000 EXPECT_LT(0, text_log[1].origin.x()); 3122 EXPECT_LT(0, text_log[second_line_start].origin.x());
3001 } 3123 }
3002 } 3124 }
3003 } 3125 }
3004 3126
3005 // Ensure strings don't wrap onto multiple lines for a sufficient available 3127 // Ensure strings don't wrap onto multiple lines for a sufficient available
3006 // width. 3128 // width.
3007 TEST_P(RenderTextHarfBuzzTest, Multiline_SufficientWidth) { 3129 TEST_P(RenderTextHarfBuzzTest, Multiline_SufficientWidth) {
3008 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", 3130 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c",
3009 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; 3131 L"\x62E\x628\x632", L"\x62E \x628 \x632" };
3010 3132
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) { 3299 for (size_t i = 0; i < arraysize(kTestScenarios); ++i) {
3178 SCOPED_TRACE(base::StringPrintf( 3300 SCOPED_TRACE(base::StringPrintf(
3179 "kTestScenarios[%" PRIuS "] %d", i, kTestScenarios[i].behavior)); 3301 "kTestScenarios[%" PRIuS "] %d", i, kTestScenarios[i].behavior));
3180 render_text->SetWordWrapBehavior(kTestScenarios[i].behavior); 3302 render_text->SetWordWrapBehavior(kTestScenarios[i].behavior);
3181 render_text->Draw(canvas()); 3303 render_text->Draw(canvas());
3182 3304
3183 ASSERT_EQ(kTestScenarios[i].num_lines, test_api()->lines().size()); 3305 ASSERT_EQ(kTestScenarios[i].num_lines, test_api()->lines().size());
3184 for (size_t j = 0; j < test_api()->lines().size(); ++j) { 3306 for (size_t j = 0; j < test_api()->lines().size(); ++j) {
3185 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j)); 3307 SCOPED_TRACE(base::StringPrintf("%" PRIuS "-th line", j));
3186 EXPECT_EQ(kTestScenarios[i].char_ranges[j], 3308 EXPECT_EQ(kTestScenarios[i].char_ranges[j],
3187 test_api()->lines()[j].segments[0].char_range); 3309 LineCharRange(test_api()->lines()[j]));
3188 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize, 3310 EXPECT_EQ(kTestScenarios[i].char_ranges[j].length() * kGlyphSize,
3189 test_api()->lines()[j].size.width()); 3311 test_api()->lines()[j].size.width());
3190 } 3312 }
3191 } 3313 }
3192 } 3314 }
3193 3315
3194 TEST_P(RenderTextHarfBuzzTest, Multiline_LineBreakerBehavior) { 3316 TEST_P(RenderTextHarfBuzzTest, Multiline_LineBreakerBehavior) {
3195 const int kGlyphSize = 5; 3317 const int kGlyphSize = 5;
3196 const struct { 3318 const struct {
3197 const wchar_t* const text; 3319 const wchar_t* const text;
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
3586 EXPECT_EQ(0U, run_list->logical_to_visual(3)); 3708 EXPECT_EQ(0U, run_list->logical_to_visual(3));
3587 } 3709 }
3588 3710
3589 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByUnicodeBlocks) { 3711 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByUnicodeBlocks) {
3590 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz(); 3712 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
3591 3713
3592 // The '\x25B6' "play character" should break runs. http://crbug.com/278913 3714 // The '\x25B6' "play character" should break runs. http://crbug.com/278913
3593 render_text->SetText(WideToUTF16(L"x\x25B6y")); 3715 render_text->SetText(WideToUTF16(L"x\x25B6y"));
3594 test_api()->EnsureLayout(); 3716 test_api()->EnsureLayout();
3595 internal::TextRunList* run_list = GetHarfBuzzRunList(); 3717 internal::TextRunList* run_list = GetHarfBuzzRunList();
3718 EXPECT_EQ(ToString16Vec({"x", "▶", "y"}), GetRuns());
3596 ASSERT_EQ(3U, run_list->size()); 3719 ASSERT_EQ(3U, run_list->size());
3597 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range); 3720 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
3598 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range); 3721 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
3599 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range); 3722 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
3600 3723
3601 render_text->SetText(WideToUTF16(L"x \x25B6 y")); 3724 render_text->SetText(WideToUTF16(L"x \x25B6 y"));
3602 test_api()->EnsureLayout(); 3725 test_api()->EnsureLayout();
3603 run_list = GetHarfBuzzRunList(); 3726 run_list = GetHarfBuzzRunList();
3604 ASSERT_EQ(4U, run_list->size()); 3727 EXPECT_EQ(ToString16Vec({"x", " ", "▶", " ", "y"}), GetRuns());
tapted 2017/06/16 07:12:36 this test actually captures the old inconsistency.
3605 EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range); 3728 ASSERT_EQ(5U, run_list->size());
3606 EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range); 3729 EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
3607 EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range); 3730 EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
3608 EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range); 3731 EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
3732 EXPECT_EQ(Range(3, 4), run_list->runs()[3]->range);
3733 EXPECT_EQ(Range(4, 5), run_list->runs()[4]->range);
3609 } 3734 }
3610 3735
3611 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByEmoji) { 3736 TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByEmoji) {
3612 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz(); 3737 RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
3613 3738
3614 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is 3739 // \xF0\x9F\x98\x81 (U+1F601) is smile icon emoji. \xE2\x9C\xA8 (U+2728) is
3615 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be 3740 // a sparkle icon. Both can be drawn with color emoji fonts, so runs should be
3616 // separated. See crbug.com/448909 3741 // separated. See crbug.com/448909
3617 render_text->SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); 3742 render_text->SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
3618 test_api()->EnsureLayout(); 3743 test_api()->EnsureLayout();
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after
4549 ::testing::Values(RENDER_TEXT_HARFBUZZ), 4674 ::testing::Values(RENDER_TEXT_HARFBUZZ),
4550 PrintRenderTextBackend()); 4675 PrintRenderTextBackend());
4551 #endif 4676 #endif
4552 4677
4553 INSTANTIATE_TEST_CASE_P(, 4678 INSTANTIATE_TEST_CASE_P(,
4554 RenderTextHarfBuzzTest, 4679 RenderTextHarfBuzzTest,
4555 ::testing::Values(RENDER_TEXT_HARFBUZZ), 4680 ::testing::Values(RENDER_TEXT_HARFBUZZ),
4556 PrintRenderTextBackend()); 4681 PrintRenderTextBackend());
4557 4682
4558 } // namespace gfx 4683 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_harfbuzz.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698