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

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

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