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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "third_party/skia/include/core/SkSurface.h" | 16 #include "third_party/skia/include/core/SkSurface.h" |
| 17 #include "ui/gfx/break_list.h" | 17 #include "ui/gfx/break_list.h" |
| 18 #include "ui/gfx/canvas.h" | 18 #include "ui/gfx/canvas.h" |
| 19 #include "ui/gfx/color_utils.h" | 19 #include "ui/gfx/color_utils.h" |
| 20 #include "ui/gfx/font.h" | 20 #include "ui/gfx/font.h" |
| 21 #include "ui/gfx/render_text_harfbuzz.h" | 21 #include "ui/gfx/render_text_harfbuzz.h" |
| 22 | 22 |
| 23 #if defined(OS_WIN) | 23 #if defined(OS_WIN) |
| 24 #include "base/win/windows_version.h" | 24 #include "base/win/windows_version.h" |
| 25 #include "ui/gfx/platform_font_win.h" | 25 #include "ui/gfx/platform_font_win.h" |
| 26 #include "ui/gfx/render_text_win.h" | |
| 27 #endif | |
| 28 | |
| 29 #if defined(OS_LINUX) && !defined(USE_OZONE) | |
| 30 #include "ui/gfx/render_text_pango.h" | |
| 31 #endif | 26 #endif |
| 32 | 27 |
| 33 using base::ASCIIToUTF16; | 28 using base::ASCIIToUTF16; |
| 34 using base::UTF8ToUTF16; | 29 using base::UTF8ToUTF16; |
| 35 using base::WideToUTF16; | 30 using base::WideToUTF16; |
| 36 using base::WideToUTF8; | 31 using base::WideToUTF8; |
| 37 | 32 |
| 38 namespace gfx { | 33 namespace gfx { |
| 39 | 34 |
| 40 namespace { | 35 namespace { |
| 41 | 36 |
| 42 // Various weak, LTR, RTL, and Bidi string cases with three characters each. | 37 // Various weak, LTR, RTL, and Bidi string cases with three characters each. |
| 43 const wchar_t kWeak[] = L" . "; | 38 const wchar_t kWeak[] = L" . "; |
| 44 const wchar_t kLtr[] = L"abc"; | 39 const wchar_t kLtr[] = L"abc"; |
| 45 const wchar_t kRtl[] = L"\x5d0\x5d1\x5d2"; | 40 const wchar_t kRtl[] = L"\x5d0\x5d1\x5d2"; |
| 46 #if !defined(OS_MACOSX) | |
| 47 const wchar_t kLtrRtl[] = L"a" L"\x5d0\x5d1"; | 41 const wchar_t kLtrRtl[] = L"a" L"\x5d0\x5d1"; |
| 48 const wchar_t kLtrRtlLtr[] = L"a" L"\x5d1" L"b"; | 42 const wchar_t kLtrRtlLtr[] = L"a" L"\x5d1" L"b"; |
| 49 const wchar_t kRtlLtr[] = L"\x5d0\x5d1" L"a"; | 43 const wchar_t kRtlLtr[] = L"\x5d0\x5d1" L"a"; |
| 50 const wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1"; | 44 const wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1"; |
| 51 #endif | |
| 52 | 45 |
| 53 // Checks whether |range| contains |index|. This is not the same as calling | 46 // Checks whether |range| contains |index|. This is not the same as calling |
| 54 // range.Contains(Range(index)), which returns true if |index| == |range.end()|. | 47 // range.Contains(Range(index)), which returns true if |index| == |range.end()|. |
| 55 bool IndexInRange(const Range& range, size_t index) { | 48 bool IndexInRange(const Range& range, size_t index) { |
| 56 return index >= range.start() && index < range.end(); | 49 return index >= range.start() && index < range.end(); |
| 57 } | 50 } |
| 58 | 51 |
| 59 base::string16 GetSelectedText(RenderText* render_text) { | 52 base::string16 GetSelectedText(RenderText* render_text) { |
| 60 return render_text->text().substr(render_text->selection().GetMin(), | 53 return render_text->text().substr(render_text->selection().GetMin(), |
| 61 render_text->selection().length()); | 54 render_text->selection().length()); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 render_text->ApplyStyle(UNDERLINE, true, Range(2, 5)); | 193 render_text->ApplyStyle(UNDERLINE, true, Range(2, 5)); |
| 201 std::vector<std::pair<size_t, bool> > expected_underline; | 194 std::vector<std::pair<size_t, bool> > expected_underline; |
| 202 expected_underline.push_back(std::pair<size_t, bool>(0, false)); | 195 expected_underline.push_back(std::pair<size_t, bool>(0, false)); |
| 203 expected_underline.push_back(std::pair<size_t, bool>(1, true)); | 196 expected_underline.push_back(std::pair<size_t, bool>(1, true)); |
| 204 expected_underline.push_back(std::pair<size_t, bool>(6, false)); | 197 expected_underline.push_back(std::pair<size_t, bool>(6, false)); |
| 205 EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsForTesting( | 198 EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsForTesting( |
| 206 expected_underline)); | 199 expected_underline)); |
| 207 #endif // OS_MACOSX | 200 #endif // OS_MACOSX |
| 208 } | 201 } |
| 209 | 202 |
| 210 #if defined(OS_LINUX) && !defined(USE_OZONE) | |
| 211 TEST_F(RenderTextTest, PangoAttributes) { | |
| 212 scoped_ptr<RenderText> render_text(RenderText::CreateNativeInstance()); | |
| 213 render_text->SetText(ASCIIToUTF16("012345678")); | |
| 214 | |
| 215 // Apply ranged BOLD/ITALIC styles and check the resulting Pango attributes. | |
| 216 render_text->ApplyStyle(BOLD, true, Range(2, 4)); | |
| 217 render_text->ApplyStyle(ITALIC, true, Range(1, 3)); | |
| 218 | |
| 219 struct { | |
| 220 int start; | |
| 221 int end; | |
| 222 bool bold; | |
| 223 bool italic; | |
| 224 } cases[] = { | |
| 225 { 0, 1, false, false }, | |
| 226 { 1, 2, false, true }, | |
| 227 { 2, 3, true, true }, | |
| 228 { 3, 4, true, false }, | |
| 229 { 4, INT_MAX, false, false }, | |
| 230 }; | |
| 231 | |
| 232 int start = 0, end = 0; | |
| 233 RenderTextPango* rt_linux = static_cast<RenderTextPango*>(render_text.get()); | |
| 234 rt_linux->EnsureLayout(); | |
| 235 PangoAttrList* attributes = pango_layout_get_attributes(rt_linux->layout_); | |
| 236 PangoAttrIterator* iter = pango_attr_list_get_iterator(attributes); | |
| 237 for (size_t i = 0; i < arraysize(cases); ++i) { | |
| 238 pango_attr_iterator_range(iter, &start, &end); | |
| 239 EXPECT_EQ(cases[i].start, start); | |
| 240 EXPECT_EQ(cases[i].end, end); | |
| 241 PangoFontDescription* font = pango_font_description_new(); | |
| 242 pango_attr_iterator_get_font(iter, font, NULL, NULL); | |
| 243 char* description_string = pango_font_description_to_string(font); | |
| 244 const base::string16 desc = ASCIIToUTF16(description_string); | |
| 245 const bool bold = desc.find(ASCIIToUTF16("Bold")) != std::string::npos; | |
| 246 EXPECT_EQ(cases[i].bold, bold); | |
| 247 const bool italic = desc.find(ASCIIToUTF16("Italic")) != std::string::npos; | |
| 248 EXPECT_EQ(cases[i].italic, italic); | |
| 249 pango_attr_iterator_next(iter); | |
| 250 pango_font_description_free(font); | |
| 251 g_free(description_string); | |
| 252 } | |
| 253 EXPECT_FALSE(pango_attr_iterator_next(iter)); | |
| 254 pango_attr_iterator_destroy(iter); | |
| 255 } | |
| 256 #endif | |
| 257 | |
| 258 // TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac | 203 // TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac |
| 259 // does not implement this yet. http://crbug.com/131618 | 204 // does not implement this yet. http://crbug.com/131618 |
| 260 #if !defined(OS_MACOSX) | 205 #if !defined(OS_MACOSX) |
| 261 void TestVisualCursorMotionInObscuredField(RenderText* render_text, | 206 void TestVisualCursorMotionInObscuredField(RenderText* render_text, |
| 262 const base::string16& text, | 207 const base::string16& text, |
| 263 bool select) { | 208 bool select) { |
| 264 ASSERT_TRUE(render_text->obscured()); | 209 ASSERT_TRUE(render_text->obscured()); |
| 265 render_text->SetText(text); | 210 render_text->SetText(text); |
| 266 int len = text.length(); | 211 int len = text.length(); |
| 267 render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select); | 212 render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select); |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 842 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); | 787 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); |
| 843 EXPECT_EQ(2U, render_text->cursor_position()); | 788 EXPECT_EQ(2U, render_text->cursor_position()); |
| 844 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); | 789 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); |
| 845 EXPECT_EQ(0U, render_text->cursor_position()); | 790 EXPECT_EQ(0U, render_text->cursor_position()); |
| 846 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); | 791 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false); |
| 847 EXPECT_EQ(0U, render_text->cursor_position()); | 792 EXPECT_EQ(0U, render_text->cursor_position()); |
| 848 } | 793 } |
| 849 #endif | 794 #endif |
| 850 | 795 |
| 851 // TODO(ckocagil): Enable for RenderTextHarfBuzz. http://crbug.com/383265 | 796 // TODO(ckocagil): Enable for RenderTextHarfBuzz. http://crbug.com/383265 |
| 797 #if defined(OS_MACOSX) | |
| 852 TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) { | 798 TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) { |
| 853 scoped_ptr<RenderText> render_text(RenderText::CreateNativeInstance()); | 799 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 854 // Meiryo UI uses single-glyph ligatures for 'ff' and 'ffi', but each letter | 800 // Meiryo UI uses single-glyph ligatures for 'ff' and 'ffi', but each letter |
| 855 // (code point) has unique bounds, so mid-glyph cursoring should be possible. | 801 // (code point) has unique bounds, so mid-glyph cursoring should be possible. |
| 856 render_text->SetFontList(FontList("Meiryo UI, 12px")); | 802 render_text->SetFontList(FontList("Meiryo UI, 12px")); |
| 857 render_text->SetText(WideToUTF16(L"ff ffi")); | 803 render_text->SetText(WideToUTF16(L"ff ffi")); |
| 858 EXPECT_EQ(0U, render_text->cursor_position()); | 804 EXPECT_EQ(0U, render_text->cursor_position()); |
| 859 for (size_t i = 0; i < render_text->text().length(); ++i) { | 805 for (size_t i = 0; i < render_text->text().length(); ++i) { |
| 860 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); | 806 render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false); |
| 861 EXPECT_EQ(i + 1, render_text->cursor_position()); | 807 EXPECT_EQ(i + 1, render_text->cursor_position()); |
| 862 } | 808 } |
| 863 EXPECT_EQ(6U, render_text->cursor_position()); | 809 EXPECT_EQ(6U, render_text->cursor_position()); |
| 864 } | 810 } |
| 811 #endif // defined(OS_MACOSX) | |
| 865 | 812 |
| 866 TEST_F(RenderTextTest, GraphemePositions) { | 813 TEST_F(RenderTextTest, GraphemePositions) { |
| 867 // LTR 2-character grapheme, LTR abc, LTR 2-character grapheme. | 814 // LTR 2-character grapheme, LTR abc, LTR 2-character grapheme. |
| 868 const base::string16 kText1 = | 815 const base::string16 kText1 = |
| 869 WideToUTF16(L"\x0915\x093f" L"abc" L"\x0915\x093f"); | 816 WideToUTF16(L"\x0915\x093f" L"abc" L"\x0915\x093f"); |
| 870 | 817 |
| 871 // LTR ab, LTR 2-character grapheme, LTR cd. | 818 // LTR ab, LTR 2-character grapheme, LTR cd. |
| 872 const base::string16 kText2 = WideToUTF16(L"ab" L"\x0915\x093f" L"cd"); | 819 const base::string16 kText2 = WideToUTF16(L"ab" L"\x0915\x093f" L"cd"); |
| 873 | 820 |
| 874 // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as | 821 // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1297 EXPECT_EQ(3U, render_text->cursor_position()); | 1244 EXPECT_EQ(3U, render_text->cursor_position()); |
| 1298 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); | 1245 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); |
| 1299 EXPECT_EQ(5U, render_text->cursor_position()); | 1246 EXPECT_EQ(5U, render_text->cursor_position()); |
| 1300 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); | 1247 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); |
| 1301 EXPECT_EQ(6U, render_text->cursor_position()); | 1248 EXPECT_EQ(6U, render_text->cursor_position()); |
| 1302 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); | 1249 render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false); |
| 1303 EXPECT_EQ(6U, render_text->cursor_position()); | 1250 EXPECT_EQ(6U, render_text->cursor_position()); |
| 1304 } | 1251 } |
| 1305 #endif | 1252 #endif |
| 1306 | 1253 |
| 1307 // TODO(ckocagil): Remove when RenderTextWin goes away. | |
| 1308 #if defined(OS_WIN) | |
| 1309 TEST_F(RenderTextTest, Win_LogicalClusters) { | |
| 1310 scoped_ptr<RenderTextWin> render_text( | |
| 1311 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 1312 | |
| 1313 const base::string16 test_string = | |
| 1314 WideToUTF16(L"\x0930\x0930\x0930\x0930\x0930"); | |
| 1315 render_text->SetText(test_string); | |
| 1316 render_text->EnsureLayout(); | |
| 1317 ASSERT_EQ(1U, render_text->runs_.size()); | |
| 1318 WORD* logical_clusters = render_text->runs_[0]->logical_clusters.get(); | |
| 1319 for (size_t i = 0; i < test_string.length(); ++i) | |
| 1320 EXPECT_EQ(i, logical_clusters[i]); | |
| 1321 } | |
| 1322 #endif // defined(OS_WIN) | |
| 1323 | |
| 1324 TEST_F(RenderTextTest, StringSizeSanity) { | 1254 TEST_F(RenderTextTest, StringSizeSanity) { |
| 1325 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1255 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1326 render_text->SetText(UTF8ToUTF16("Hello World")); | 1256 render_text->SetText(UTF8ToUTF16("Hello World")); |
| 1327 const Size string_size = render_text->GetStringSize(); | 1257 const Size string_size = render_text->GetStringSize(); |
| 1328 EXPECT_GT(string_size.width(), 0); | 1258 EXPECT_GT(string_size.width(), 0); |
| 1329 EXPECT_GT(string_size.height(), 0); | 1259 EXPECT_GT(string_size.height(), 0); |
| 1330 } | 1260 } |
| 1331 | 1261 |
| 1332 TEST_F(RenderTextTest, StringSizeLongStrings) { | 1262 TEST_F(RenderTextTest, StringSizeLongStrings) { |
| 1333 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1263 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1926 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1856 render_text->SetText(WideToUTF16(kTestStrings[i])); |
| 1927 const int expected_width = render_text->GetStringSize().width(); | 1857 const int expected_width = render_text->GetStringSize().width(); |
| 1928 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); | 1858 render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD)); |
| 1929 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); | 1859 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); |
| 1930 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119 | 1860 // Drawing the text should not DCHECK or crash; see http://crbug.com/262119 |
| 1931 render_text->Draw(&canvas); | 1861 render_text->Draw(&canvas); |
| 1932 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); | 1862 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); |
| 1933 } | 1863 } |
| 1934 } | 1864 } |
| 1935 | 1865 |
| 1936 #if defined(OS_WIN) | |
| 1937 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | 1866 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. |
| 1938 // Ensure strings wrap onto multiple lines for a small available width. | 1867 // Ensure strings wrap onto multiple lines for a small available width. |
| 1939 TEST_F(RenderTextTest, Multiline_MinWidth) { | 1868 TEST_F(RenderTextTest, DISABLED_Multiline_MinWidth) { |
| 1940 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, | 1869 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, |
| 1941 kRtlLtr, kRtlLtrRtl }; | 1870 kRtlLtr, kRtlLtrRtl }; |
| 1942 | 1871 |
| 1943 scoped_ptr<RenderTextWin> render_text( | 1872 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1944 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 1945 render_text->SetDisplayRect(Rect(1, 1000)); | 1873 render_text->SetDisplayRect(Rect(1, 1000)); |
| 1946 render_text->SetMultiline(true); | 1874 render_text->SetMultiline(true); |
| 1947 Canvas canvas; | 1875 Canvas canvas; |
| 1948 | 1876 |
| 1949 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1877 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1950 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1878 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1951 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1879 render_text->SetText(WideToUTF16(kTestStrings[i])); |
| 1952 render_text->Draw(&canvas); | 1880 render_text->Draw(&canvas); |
| 1953 EXPECT_GT(render_text->lines_.size(), 1U); | 1881 EXPECT_GT(render_text->lines_.size(), 1U); |
| 1954 } | 1882 } |
| 1955 } | 1883 } |
| 1956 | 1884 |
| 1957 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | 1885 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. |
| 1958 // Ensure strings wrap onto multiple lines for a normal available width. | 1886 // Ensure strings wrap onto multiple lines for a normal available width. |
| 1959 TEST_F(RenderTextTest, Multiline_NormalWidth) { | 1887 TEST_F(RenderTextTest, DISABLED_Multiline_NormalWidth) { |
| 1960 const struct { | 1888 const struct { |
| 1961 const wchar_t* const text; | 1889 const wchar_t* const text; |
| 1962 const Range first_line_char_range; | 1890 const Range first_line_char_range; |
| 1963 const Range second_line_char_range; | 1891 const Range second_line_char_range; |
| 1964 } kTestStrings[] = { | 1892 } kTestStrings[] = { |
| 1965 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, | 1893 { L"abc defg hijkl", Range(0, 9), Range(9, 14) }, |
| 1966 { L"qwertyzxcvbn", Range(0, 8), Range(8, 12) }, | 1894 { L"qwertyzxcvbn", Range(0, 8), Range(8, 12) }, |
| 1967 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD", | 1895 { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD", |
| 1968 Range(4, 10), Range(0, 4) } | 1896 Range(4, 10), Range(0, 4) } |
| 1969 }; | 1897 }; |
| 1970 | 1898 |
| 1971 scoped_ptr<RenderTextWin> render_text( | 1899 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1972 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 1973 render_text->SetDisplayRect(Rect(50, 1000)); | 1900 render_text->SetDisplayRect(Rect(50, 1000)); |
| 1974 render_text->SetMultiline(true); | 1901 render_text->SetMultiline(true); |
| 1975 Canvas canvas; | 1902 Canvas canvas; |
| 1976 | 1903 |
| 1977 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1904 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 1978 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1905 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 1979 render_text->SetText(WideToUTF16(kTestStrings[i].text)); | 1906 render_text->SetText(WideToUTF16(kTestStrings[i].text)); |
| 1980 render_text->Draw(&canvas); | 1907 render_text->Draw(&canvas); |
| 1981 ASSERT_EQ(2U, render_text->lines_.size()); | 1908 ASSERT_EQ(2U, render_text->lines_.size()); |
| 1982 ASSERT_EQ(1U, render_text->lines_[0].segments.size()); | 1909 ASSERT_EQ(1U, render_text->lines_[0].segments.size()); |
| 1983 EXPECT_EQ(kTestStrings[i].first_line_char_range, | 1910 EXPECT_EQ(kTestStrings[i].first_line_char_range, |
| 1984 render_text->lines_[0].segments[0].char_range); | 1911 render_text->lines_[0].segments[0].char_range); |
| 1985 ASSERT_EQ(1U, render_text->lines_[1].segments.size()); | 1912 ASSERT_EQ(1U, render_text->lines_[1].segments.size()); |
| 1986 EXPECT_EQ(kTestStrings[i].second_line_char_range, | 1913 EXPECT_EQ(kTestStrings[i].second_line_char_range, |
| 1987 render_text->lines_[1].segments[0].char_range); | 1914 render_text->lines_[1].segments[0].char_range); |
| 1988 } | 1915 } |
| 1989 } | 1916 } |
| 1990 | 1917 |
| 1991 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | 1918 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. |
| 1992 // Ensure strings don't wrap onto multiple lines for a sufficient available | 1919 // Ensure strings don't wrap onto multiple lines for a sufficient available |
| 1993 // width. | 1920 // width. |
| 1994 TEST_F(RenderTextTest, Multiline_SufficientWidth) { | 1921 TEST_F(RenderTextTest, DISABLED_Multiline_SufficientWidth) { |
| 1995 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", | 1922 const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c", |
| 1996 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; | 1923 L"\x62E\x628\x632", L"\x62E \x628 \x632" }; |
| 1997 | 1924 |
| 1998 scoped_ptr<RenderTextWin> render_text( | 1925 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1999 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 2000 render_text->SetDisplayRect(Rect(30, 1000)); | 1926 render_text->SetDisplayRect(Rect(30, 1000)); |
| 2001 render_text->SetMultiline(true); | 1927 render_text->SetMultiline(true); |
| 2002 Canvas canvas; | 1928 Canvas canvas; |
| 2003 | 1929 |
| 2004 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1930 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 2005 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1931 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 2006 render_text->SetText(WideToUTF16(kTestStrings[i])); | 1932 render_text->SetText(WideToUTF16(kTestStrings[i])); |
| 2007 render_text->Draw(&canvas); | 1933 render_text->Draw(&canvas); |
| 2008 EXPECT_EQ(1U, render_text->lines_.size()); | 1934 EXPECT_EQ(1U, render_text->lines_.size()); |
| 2009 } | 1935 } |
| 2010 } | 1936 } |
| 2011 | 1937 |
| 2012 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. | 1938 // TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline. |
| 2013 TEST_F(RenderTextTest, Multiline_Newline) { | 1939 TEST_F(RenderTextTest, DISABLED_Multiline_Newline) { |
| 2014 const struct { | 1940 const struct { |
| 2015 const wchar_t* const text; | 1941 const wchar_t* const text; |
| 2016 // Ranges of the characters on each line preceding the newline. | 1942 // Ranges of the characters on each line preceding the newline. |
| 2017 const Range first_line_char_range; | 1943 const Range first_line_char_range; |
| 2018 const Range second_line_char_range; | 1944 const Range second_line_char_range; |
| 2019 } kTestStrings[] = { | 1945 } kTestStrings[] = { |
| 2020 { L"abc\ndef", Range(0, 3), Range(4, 7) }, | 1946 { L"abc\ndef", Range(0, 3), Range(4, 7) }, |
| 2021 { L"a \n b ", Range(0, 2), Range(3, 6) }, | 1947 { L"a \n b ", Range(0, 2), Range(3, 6) }, |
| 2022 { L"\n" , Range::InvalidRange(), Range::InvalidRange() } | 1948 { L"\n" , Range::InvalidRange(), Range::InvalidRange() } |
| 2023 }; | 1949 }; |
| 2024 | 1950 |
| 2025 scoped_ptr<RenderTextWin> render_text( | 1951 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 2026 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 2027 render_text->SetDisplayRect(Rect(200, 1000)); | 1952 render_text->SetDisplayRect(Rect(200, 1000)); |
| 2028 render_text->SetMultiline(true); | 1953 render_text->SetMultiline(true); |
| 2029 Canvas canvas; | 1954 Canvas canvas; |
| 2030 | 1955 |
| 2031 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 1956 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 2032 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | 1957 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); |
| 2033 render_text->SetText(WideToUTF16(kTestStrings[i].text)); | 1958 render_text->SetText(WideToUTF16(kTestStrings[i].text)); |
| 2034 render_text->Draw(&canvas); | 1959 render_text->Draw(&canvas); |
| 2035 | 1960 |
| 2036 ASSERT_EQ(2U, render_text->lines_.size()); | 1961 ASSERT_EQ(2U, render_text->lines_.size()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2049 | 1974 |
| 2050 const Range second_expected_range = kTestStrings[i].second_line_char_range; | 1975 const Range second_expected_range = kTestStrings[i].second_line_char_range; |
| 2051 ASSERT_EQ(second_expected_range.IsValid() ? 1U : 0U, | 1976 ASSERT_EQ(second_expected_range.IsValid() ? 1U : 0U, |
| 2052 render_text->lines_[1].segments.size()); | 1977 render_text->lines_[1].segments.size()); |
| 2053 if (second_expected_range.IsValid()) | 1978 if (second_expected_range.IsValid()) |
| 2054 EXPECT_EQ(second_expected_range, | 1979 EXPECT_EQ(second_expected_range, |
| 2055 render_text->lines_[1].segments[0].char_range); | 1980 render_text->lines_[1].segments[0].char_range); |
| 2056 } | 1981 } |
| 2057 } | 1982 } |
| 2058 | 1983 |
| 2059 // TODO(ckocagil): Remove when RenderTextWin goes away. | |
| 2060 TEST_F(RenderTextTest, BreakRunsByUnicodeBlocks) { | |
| 2061 scoped_ptr<RenderTextWin> render_text( | |
| 2062 static_cast<RenderTextWin*>(RenderText::CreateNativeInstance())); | |
| 2063 | |
| 2064 // The '\x25B6' "play character" should break runs. http://crbug.com/278913 | |
| 2065 render_text->SetText(WideToUTF16(L"x\x25B6y")); | |
|
msw
2015/02/02 22:52:55
I wonder if we could preserve a similar test for H
Daniel Erat
2015/02/02 23:10:31
it's collapsed, but it looks like we already have
| |
| 2066 render_text->EnsureLayout(); | |
| 2067 ASSERT_EQ(3U, render_text->runs_.size()); | |
| 2068 EXPECT_EQ(Range(0, 1), render_text->runs_[0]->range); | |
| 2069 EXPECT_EQ(Range(1, 2), render_text->runs_[1]->range); | |
| 2070 EXPECT_EQ(Range(2, 3), render_text->runs_[2]->range); | |
| 2071 | |
| 2072 render_text->SetText(WideToUTF16(L"x \x25B6 y")); | |
| 2073 render_text->EnsureLayout(); | |
| 2074 ASSERT_EQ(3U, render_text->runs_.size()); | |
| 2075 EXPECT_EQ(Range(0, 2), render_text->runs_[0]->range); | |
| 2076 EXPECT_EQ(Range(2, 3), render_text->runs_[1]->range); | |
| 2077 EXPECT_EQ(Range(3, 5), render_text->runs_[2]->range); | |
| 2078 } | |
| 2079 #endif // defined(OS_WIN) | |
| 2080 | |
| 2081 // Test TextRunHarfBuzz's cluster finding logic. | 1984 // Test TextRunHarfBuzz's cluster finding logic. |
| 2082 TEST_F(RenderTextTest, HarfBuzz_Clusters) { | 1985 TEST_F(RenderTextTest, HarfBuzz_Clusters) { |
| 2083 struct { | 1986 struct { |
| 2084 uint32 glyph_to_char[4]; | 1987 uint32 glyph_to_char[4]; |
| 2085 Range chars[4]; | 1988 Range chars[4]; |
| 2086 Range glyphs[4]; | 1989 Range glyphs[4]; |
| 2087 bool is_rtl; | 1990 bool is_rtl; |
| 2088 } cases[] = { | 1991 } cases[] = { |
| 2089 { // From string "A B C D" to glyphs "a b c d". | 1992 { // From string "A B C D" to glyphs "a b c d". |
| 2090 { 0, 1, 2, 3 }, | 1993 { 0, 1, 2, 3 }, |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2261 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); | 2164 render_text.SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8")); |
| 2262 render_text.EnsureLayout(); | 2165 render_text.EnsureLayout(); |
| 2263 ASSERT_EQ(4U, render_text.runs_.size()); | 2166 ASSERT_EQ(4U, render_text.runs_.size()); |
| 2264 EXPECT_EQ(Range(0, 1), render_text.runs_[0]->range); | 2167 EXPECT_EQ(Range(0, 1), render_text.runs_[0]->range); |
| 2265 // The length is 2 since U+1F601 is represented as a surrogate pair in UTF16. | 2168 // The length is 2 since U+1F601 is represented as a surrogate pair in UTF16. |
| 2266 EXPECT_EQ(Range(1, 3), render_text.runs_[1]->range); | 2169 EXPECT_EQ(Range(1, 3), render_text.runs_[1]->range); |
| 2267 EXPECT_EQ(Range(3, 4), render_text.runs_[2]->range); | 2170 EXPECT_EQ(Range(3, 4), render_text.runs_[2]->range); |
| 2268 EXPECT_EQ(Range(4, 5), render_text.runs_[3]->range); | 2171 EXPECT_EQ(Range(4, 5), render_text.runs_[3]->range); |
| 2269 } | 2172 } |
| 2270 | 2173 |
| 2271 // Disabled on Mac because RenderTextMac doesn't implement GetGlyphBounds. | |
| 2272 #if !defined(OS_MACOSX) | |
| 2273 TEST_F(RenderTextTest, GlyphBounds) { | 2174 TEST_F(RenderTextTest, GlyphBounds) { |
| 2274 const wchar_t* kTestStrings[] = { | 2175 const wchar_t* kTestStrings[] = { |
| 2275 L"asdf 1234 qwer", L"\x0647\x0654", L"\x0645\x0631\x062D\x0628\x0627" | 2176 L"asdf 1234 qwer", L"\x0647\x0654", L"\x0645\x0631\x062D\x0628\x0627" |
| 2276 }; | 2177 }; |
| 2277 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | |
| 2278 | |
| 2279 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | |
| 2280 render_text->SetText(WideToUTF16(kTestStrings[i])); | |
| 2281 render_text->EnsureLayout(); | |
| 2282 | |
| 2283 for (size_t j = 0; j < render_text->text().length(); ++j) | |
| 2284 EXPECT_FALSE(render_text->GetGlyphBounds(j).is_empty()); | |
| 2285 } | |
| 2286 } | |
| 2287 #endif | |
| 2288 | |
| 2289 // Remove this after making RTHB default in favor of RenderTextTest.GlyphBounds. | |
| 2290 TEST_F(RenderTextTest, HarfBuzz_GlyphBounds) { | |
| 2291 const wchar_t* kTestStrings[] = { | |
| 2292 L"asdf 1234 qwer", L"\x0647\x0654", L"\x0645\x0631\x062D\x0628\x0627" | |
| 2293 }; | |
| 2294 scoped_ptr<RenderText> render_text(new RenderTextHarfBuzz); | 2178 scoped_ptr<RenderText> render_text(new RenderTextHarfBuzz); |
| 2295 | 2179 |
| 2296 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | 2180 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { |
| 2297 render_text->SetText(WideToUTF16(kTestStrings[i])); | 2181 render_text->SetText(WideToUTF16(kTestStrings[i])); |
| 2298 render_text->EnsureLayout(); | 2182 render_text->EnsureLayout(); |
| 2299 | 2183 |
| 2300 for (size_t j = 0; j < render_text->text().length(); ++j) | 2184 for (size_t j = 0; j < render_text->text().length(); ++j) |
| 2301 EXPECT_FALSE(render_text->GetGlyphBounds(j).is_empty()); | 2185 EXPECT_FALSE(render_text->GetGlyphBounds(j).is_empty()); |
| 2302 } | 2186 } |
| 2303 } | 2187 } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2459 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); | 2343 base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); |
| 2460 | 2344 |
| 2461 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 2345 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 2462 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); | 2346 render_text->SetDisplayRect(Rect(0, 0, 25, 25)); |
| 2463 render_text->SetFontList(font_list); | 2347 render_text->SetFontList(font_list); |
| 2464 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); | 2348 EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); |
| 2465 } | 2349 } |
| 2466 #endif | 2350 #endif |
| 2467 | 2351 |
| 2468 } // namespace gfx | 2352 } // namespace gfx |
| OLD | NEW |