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

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

Issue 16867016: Windows implementation of multiline RenderText (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Mike's comments 2 Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/render_text.h" 5 #include "ui/gfx/render_text.h"
6 6
7 #include <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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698