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