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