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/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "ui/gfx/break_list.h" | 14 #include "ui/gfx/break_list.h" |
| 14 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 15 | 16 |
| 16 #if defined(OS_WIN) | 17 #if defined(OS_WIN) |
| 17 #include "base/win/windows_version.h" | 18 #include "base/win/windows_version.h" |
| 18 #include "ui/gfx/render_text_win.h" | 19 #include "ui/gfx/render_text_win.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 EXPECT_EQ(expected[i], render_text->selection_model()); | 73 EXPECT_EQ(expected[i], render_text->selection_model()); |
| 73 render_text->MoveCursor(CHARACTER_BREAK, direction, false); | 74 render_text->MoveCursor(CHARACTER_BREAK, direction, false); |
| 74 } | 75 } |
| 75 // Check that cursoring is clamped at the line edge. | 76 // Check that cursoring is clamped at the line edge. |
| 76 EXPECT_EQ(expected.back(), render_text->selection_model()); | 77 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 77 // Check that it is the line edge. | 78 // Check that it is the line edge. |
| 78 render_text->MoveCursor(LINE_BREAK, direction, false); | 79 render_text->MoveCursor(LINE_BREAK, direction, false); |
| 79 EXPECT_EQ(expected.back(), render_text->selection_model()); | 80 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 80 } | 81 } |
| 81 | 82 |
| 83 // For segments in the same run, checks the continuity and order of |x_range| | |
| 84 // and |char_range| fields. | |
| 85 #if defined(OS_WIN) | |
| 86 void CheckLineIntegrity(const std::vector<internal::Line>& lines, | |
| 87 const ScopedVector<internal::TextRun>& runs) { | |
| 88 size_t previous_segment_line = 0; | |
| 89 const internal::LineSegment* previous_segment = NULL; | |
| 90 | |
| 91 for (size_t i = 0; i < lines.size(); ++i) { | |
| 92 SCOPED_TRACE(base::StringPrintf("line %" PRIuS, i)); | |
| 93 for (size_t j = 0; j < lines[i].segments.size(); ++j) { | |
| 94 SCOPED_TRACE(base::StringPrintf("segment %" PRIuS, j)); | |
| 95 const internal::LineSegment* const segment = &lines[i].segments[j]; | |
|
Alexei Svitkine (slow)
2013/08/27 15:40:38
Nit: I don't think we usually put const after the
ckocagil
2013/08/28 19:16:26
The const after the * makes the pointer itself con
Alexei Svitkine (slow)
2013/08/28 21:27:46
The other ones only seem to do it for arrays of co
ckocagil
2013/08/30 16:53:36
Done.
| |
| 96 internal::TextRun* const run = runs[segment->run]; | |
| 97 | |
| 98 if (!previous_segment) { | |
| 99 previous_segment = segment; | |
| 100 } else if (runs[previous_segment->run] != run) { | |
| 101 previous_segment = NULL; | |
| 102 } else { | |
| 103 SCOPED_TRACE(run->script_analysis.fRTL ? "RTL" : "LTR"); | |
| 104 SCOPED_TRACE(base::StringPrintf( | |
| 105 "current x_range: [%" PRIuS ", %" PRIuS ")", | |
|
msw
2013/08/27 01:30:52
nit: printing ui::Range ints with PRIuS (unsigned
ckocagil
2013/08/28 18:01:45
Is it? ui::Range::start() and end() both return si
msw
2013/08/30 00:42:28
Hmm, I mistakenly thought they were ints; glad you
| |
| 106 segment->x_range.start(), segment->x_range.end())); | |
| 107 SCOPED_TRACE(base::StringPrintf( | |
| 108 "previous x_range: [%" PRIuS ", %" PRIuS ")", | |
| 109 previous_segment->x_range.start(), | |
| 110 previous_segment->x_range.end())); | |
| 111 | |
| 112 EXPECT_EQ(previous_segment->char_range.end(), | |
| 113 segment->char_range.start()); | |
| 114 if (!run->script_analysis.fRTL) | |
| 115 EXPECT_EQ(previous_segment->x_range.end(), segment->x_range.start()); | |
| 116 else if (i != previous_segment_line) | |
| 117 EXPECT_EQ(segment->x_range.end(), previous_segment->x_range.start()); | |
| 118 | |
| 119 previous_segment = segment; | |
| 120 previous_segment_line = i; | |
| 121 } | |
| 122 } | |
| 123 } | |
| 124 } | |
| 125 #endif // defined(OS_WIN) | |
| 126 | |
| 82 } // namespace | 127 } // namespace |
| 83 | 128 |
| 84 class RenderTextTest : public testing::Test { | 129 class RenderTextTest : public testing::Test { |
| 85 }; | 130 }; |
| 86 | 131 |
| 87 TEST_F(RenderTextTest, DefaultStyle) { | 132 TEST_F(RenderTextTest, DefaultStyle) { |
| 88 // Check the default styles applied to new instances and adjusted text. | 133 // Check the default styles applied to new instances and adjusted text. |
| 89 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 134 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 90 EXPECT_TRUE(render_text->text().empty()); | 135 EXPECT_TRUE(render_text->text().empty()); |
| 91 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; | 136 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; |
| (...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1287 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1332 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1288 render_text->SetText(ASCIIToUTF16("abcdefg")); | 1333 render_text->SetText(ASCIIToUTF16("abcdefg")); |
| 1289 render_text->SetFontList(FontList("Arial, 13px")); | 1334 render_text->SetFontList(FontList("Arial, 13px")); |
| 1290 | 1335 |
| 1291 // Set display area's size equal to the font size. | 1336 // Set display area's size equal to the font size. |
| 1292 const Size font_size(render_text->GetContentWidth(), | 1337 const Size font_size(render_text->GetContentWidth(), |
| 1293 render_text->GetStringSize().height()); | 1338 render_text->GetStringSize().height()); |
| 1294 Rect display_rect(font_size); | 1339 Rect display_rect(font_size); |
| 1295 render_text->SetDisplayRect(display_rect); | 1340 render_text->SetDisplayRect(display_rect); |
| 1296 | 1341 |
| 1297 Vector2d offset = render_text->GetTextOffset(); | 1342 Vector2d offset = render_text->GetLineOffset(0); |
| 1298 EXPECT_TRUE(offset.IsZero()); | 1343 EXPECT_TRUE(offset.IsZero()); |
| 1299 | 1344 |
| 1300 // Set display area's size greater than font size. | 1345 // Set display area's size greater than font size. |
| 1301 const int kEnlargement = 2; | 1346 const int kEnlargement = 2; |
| 1302 display_rect.Inset(0, 0, -kEnlargement, -kEnlargement); | 1347 display_rect.Inset(0, 0, -kEnlargement, -kEnlargement); |
| 1303 render_text->SetDisplayRect(display_rect); | 1348 render_text->SetDisplayRect(display_rect); |
| 1304 | 1349 |
| 1305 // Check the default horizontal and vertical alignment. | 1350 // Check the default horizontal and vertical alignment. |
| 1306 offset = render_text->GetTextOffset(); | 1351 offset = render_text->GetLineOffset(0); |
| 1307 EXPECT_EQ(kEnlargement / 2, offset.y()); | 1352 EXPECT_EQ(kEnlargement / 2, offset.y()); |
| 1308 EXPECT_EQ(0, offset.x()); | 1353 EXPECT_EQ(0, offset.x()); |
| 1309 | 1354 |
| 1310 // Check explicitly setting the horizontal alignment. | 1355 // Check explicitly setting the horizontal alignment. |
| 1311 render_text->SetHorizontalAlignment(ALIGN_LEFT); | 1356 render_text->SetHorizontalAlignment(ALIGN_LEFT); |
| 1312 offset = render_text->GetTextOffset(); | 1357 offset = render_text->GetLineOffset(0); |
| 1313 EXPECT_EQ(0, offset.x()); | 1358 EXPECT_EQ(0, offset.x()); |
| 1314 render_text->SetHorizontalAlignment(ALIGN_CENTER); | 1359 render_text->SetHorizontalAlignment(ALIGN_CENTER); |
| 1315 offset = render_text->GetTextOffset(); | 1360 offset = render_text->GetLineOffset(0); |
| 1316 EXPECT_EQ(kEnlargement / 2, offset.x()); | 1361 EXPECT_EQ(kEnlargement / 2, offset.x()); |
| 1317 render_text->SetHorizontalAlignment(ALIGN_RIGHT); | 1362 render_text->SetHorizontalAlignment(ALIGN_RIGHT); |
| 1318 offset = render_text->GetTextOffset(); | 1363 offset = render_text->GetLineOffset(0); |
| 1319 EXPECT_EQ(kEnlargement, offset.x()); | 1364 EXPECT_EQ(kEnlargement, offset.x()); |
| 1320 | 1365 |
| 1321 // Check explicitly setting the vertical alignment. | 1366 // Check explicitly setting the vertical alignment. |
| 1322 render_text->SetVerticalAlignment(ALIGN_TOP); | 1367 render_text->SetVerticalAlignment(ALIGN_TOP); |
| 1323 offset = render_text->GetTextOffset(); | 1368 offset = render_text->GetLineOffset(0); |
| 1324 EXPECT_EQ(0, offset.y()); | 1369 EXPECT_EQ(0, offset.y()); |
| 1325 render_text->SetVerticalAlignment(ALIGN_VCENTER); | 1370 render_text->SetVerticalAlignment(ALIGN_VCENTER); |
| 1326 offset = render_text->GetTextOffset(); | 1371 offset = render_text->GetLineOffset(0); |
| 1327 EXPECT_EQ(kEnlargement / 2, offset.y()); | 1372 EXPECT_EQ(kEnlargement / 2, offset.y()); |
| 1328 render_text->SetVerticalAlignment(ALIGN_BOTTOM); | 1373 render_text->SetVerticalAlignment(ALIGN_BOTTOM); |
| 1329 offset = render_text->GetTextOffset(); | 1374 offset = render_text->GetLineOffset(0); |
| 1330 EXPECT_EQ(kEnlargement, offset.y()); | 1375 EXPECT_EQ(kEnlargement, offset.y()); |
| 1331 | 1376 |
| 1332 SetRTL(was_rtl); | 1377 SetRTL(was_rtl); |
| 1333 } | 1378 } |
| 1334 | 1379 |
| 1335 TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { | 1380 TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) { |
| 1336 // This only checks the default horizontal alignment in RTL mode; all other | 1381 // This only checks the default horizontal alignment in RTL mode; all other |
| 1337 // GetTextOffset() attributes are checked by the test above. | 1382 // GetLineOffset(0) attributes are checked by the test above. |
| 1338 const bool was_rtl = base::i18n::IsRTL(); | 1383 const bool was_rtl = base::i18n::IsRTL(); |
| 1339 SetRTL(true); | 1384 SetRTL(true); |
| 1340 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 1385 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 1341 render_text->SetText(ASCIIToUTF16("abcdefg")); | 1386 render_text->SetText(ASCIIToUTF16("abcdefg")); |
| 1342 render_text->SetFontList(FontList("Arial, 13px")); | 1387 render_text->SetFontList(FontList("Arial, 13px")); |
| 1343 const int kEnlargement = 2; | 1388 const int kEnlargement = 2; |
| 1344 const Size font_size(render_text->GetContentWidth() + kEnlargement, | 1389 const Size font_size(render_text->GetContentWidth() + kEnlargement, |
| 1345 render_text->GetStringSize().height()); | 1390 render_text->GetStringSize().height()); |
| 1346 Rect display_rect(font_size); | 1391 Rect display_rect(font_size); |
| 1347 render_text->SetDisplayRect(display_rect); | 1392 render_text->SetDisplayRect(display_rect); |
| 1348 Vector2d offset = render_text->GetTextOffset(); | 1393 Vector2d offset = render_text->GetLineOffset(0); |
| 1349 EXPECT_EQ(kEnlargement, offset.x()); | 1394 EXPECT_EQ(kEnlargement, offset.x()); |
| 1350 SetRTL(was_rtl); | 1395 SetRTL(was_rtl); |
| 1351 } | 1396 } |
| 1352 | 1397 |
| 1353 TEST_F(RenderTextTest, SameFontForParentheses) { | 1398 TEST_F(RenderTextTest, SameFontForParentheses) { |
| 1354 struct { | 1399 struct { |
| 1355 const char16 left_char; | 1400 const char16 left_char; |
| 1356 const char16 right_char; | 1401 const char16 right_char; |
| 1357 } punctuation_pairs[] = { | 1402 } punctuation_pairs[] = { |
| 1358 { '(', ')' }, | 1403 { '(', ')' }, |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1644 const int expected_width = render_text->GetStringSize().width(); | 1689 const int expected_width = render_text->GetStringSize().width(); |
| 1645 render_text->MoveCursorTo(SelectionModel(ui::Range(0, 1), CURSOR_FORWARD)); | 1690 render_text->MoveCursorTo(SelectionModel(ui::Range(0, 1), CURSOR_FORWARD)); |
| 1646 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); | 1691 EXPECT_EQ(expected_width, render_text->GetStringSize().width()); |
| 1647 // Draw the text. It shouldn't hit any DCHECKs or crash. | 1692 // Draw the text. It shouldn't hit any DCHECKs or crash. |
| 1648 // See http://crbug.com/214150 | 1693 // See http://crbug.com/214150 |
| 1649 render_text->Draw(&canvas); | 1694 render_text->Draw(&canvas); |
| 1650 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); | 1695 render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD)); |
| 1651 } | 1696 } |
| 1652 } | 1697 } |
| 1653 | 1698 |
| 1699 #if defined(OS_WIN) | |
| 1700 TEST_F(RenderTextTest, Multiline_MinWidth) { | |
| 1701 const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, | |
| 1702 kRtlLtr, kRtlLtrRtl }; | |
| 1703 | |
| 1704 scoped_ptr<RenderTextWin> render_text( | |
| 1705 static_cast<RenderTextWin*>(RenderText::CreateInstance())); | |
| 1706 render_text->SetDisplayRect(Rect(Point(), Size(1, 1000))); | |
| 1707 render_text->SetMultiline(true); | |
| 1708 Canvas canvas; | |
| 1709 | |
| 1710 for (size_t i = 0; i < arraysize(kTestStrings); ++i) { | |
| 1711 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | |
| 1712 render_text->SetText(WideToUTF16(kTestStrings[i])); | |
| 1713 render_text->Draw(&canvas); | |
|
msw
2013/08/27 01:30:52
Is it sufficient to EnsureLayout instead of callin
ckocagil
2013/08/28 18:01:45
Without Draw() we won't hit the DrawVisualText() D
| |
| 1714 CheckLineIntegrity(render_text->lines_, render_text->runs_); | |
| 1715 } | |
| 1716 } | |
| 1717 | |
| 1718 TEST_F(RenderTextTest, Multiline_NormalWidth) { | |
| 1719 const struct { | |
| 1720 wchar_t* text; | |
| 1721 ui::Range first_line; | |
| 1722 ui::Range second_line; | |
| 1723 } kTestStrings[] = { | |
| 1724 { L"abc defg hijkl mnop qrstuv wxyz", ui::Range(0, 15), ui::Range(15, 31) }, | |
|
msw
2013/08/27 01:30:52
nit: these test cases could be covered with 50px w
ckocagil
2013/08/28 18:01:45
Done.
| |
| 1725 { L"qwertyuiopasdfghjklzxcvbnm", ui::Range(0, 17), ui::Range(17, 26) }, | |
| 1726 { L"\x0647\x0646\x0627\x0643 \x0627\x0644\x062A\x0641\x0627\x062D \x0648" | |
| 1727 L"\x0627\x0644\x0628\x0637\x0627\x0637\x0627 \x0641\x064A", | |
| 1728 ui::Range(0, 21), ui::Range(21, 23) } | |
| 1729 }; | |
| 1730 | |
| 1731 scoped_ptr<RenderTextWin> render_text( | |
| 1732 static_cast<RenderTextWin*>(RenderText::CreateInstance())); | |
| 1733 render_text->SetDisplayRect(Rect(Point(), Size(100, 1000))); | |
| 1734 render_text->SetMultiline(true); | |
| 1735 Canvas canvas; | |
| 1736 | |
| 1737 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) { | |
| 1738 SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i)); | |
| 1739 render_text->SetText(WideToUTF16(kTestStrings[i].text)); | |
| 1740 render_text->Draw(&canvas); | |
| 1741 CheckLineIntegrity(render_text->lines_, render_text->runs_); | |
| 1742 ASSERT_EQ(2U, render_text->lines_.size()); | |
| 1743 ASSERT_EQ(1U, render_text->lines_[0].segments.size()); | |
| 1744 EXPECT_EQ(kTestStrings[i].first_line, | |
| 1745 render_text->lines_[0].segments[0].char_range); | |
| 1746 ASSERT_EQ(1U, render_text->lines_[1].segments.size()); | |
| 1747 EXPECT_EQ(kTestStrings[i].second_line, | |
| 1748 render_text->lines_[1].segments[0].char_range); | |
| 1749 } | |
| 1750 } | |
| 1751 #endif // defined(OS_WIN) | |
| 1752 | |
| 1654 } // namespace gfx | 1753 } // namespace gfx |
| OLD | NEW |