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 "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/strings/stringprintf.h" |
8 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "ui/gfx/break_list.h" | 11 #include "ui/gfx/break_list.h" |
11 | 12 |
12 #if defined(OS_WIN) | 13 #if defined(OS_WIN) |
13 #include "base/win/windows_version.h" | 14 #include "base/win/windows_version.h" |
14 #endif | 15 #endif |
15 | 16 |
16 #if defined(OS_LINUX) | 17 #if defined(OS_LINUX) |
17 #include "ui/gfx/render_text_linux.h" | 18 #include "ui/gfx/render_text_linux.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 void SetRTL(bool rtl) { | 51 void SetRTL(bool rtl) { |
51 // Override the current locale/direction. | 52 // Override the current locale/direction. |
52 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en"); | 53 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en"); |
53 #if defined(TOOLKIT_GTK) | 54 #if defined(TOOLKIT_GTK) |
54 // Do the same for GTK, which does not rely on the ICU default locale. | 55 // Do the same for GTK, which does not rely on the ICU default locale. |
55 gtk_widget_set_default_direction(rtl ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); | 56 gtk_widget_set_default_direction(rtl ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); |
56 #endif | 57 #endif |
57 EXPECT_EQ(rtl, base::i18n::IsRTL()); | 58 EXPECT_EQ(rtl, base::i18n::IsRTL()); |
58 } | 59 } |
59 | 60 |
| 61 // Ensure cursor movement in the specified |direction| yields |expected| values. |
| 62 void RunMoveCursorLeftRightTest(RenderText* render_text, |
| 63 const std::vector<SelectionModel>& expected, |
| 64 VisualCursorDirection direction) { |
| 65 for (size_t i = 0; i < expected.size(); ++i) { |
| 66 SCOPED_TRACE(base::StringPrintf("Going %s; expected value index %d.", |
| 67 direction == CURSOR_LEFT ? "left" : "right", static_cast<int>(i))); |
| 68 EXPECT_EQ(expected[i], render_text->selection_model()); |
| 69 render_text->MoveCursor(CHARACTER_BREAK, direction, false); |
| 70 } |
| 71 // Check that cursoring is clamped at the line edge. |
| 72 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 73 // Check that it is the line edge. |
| 74 render_text->MoveCursor(LINE_BREAK, direction, false); |
| 75 EXPECT_EQ(expected.back(), render_text->selection_model()); |
| 76 } |
| 77 |
60 } // namespace | 78 } // namespace |
61 | 79 |
62 class RenderTextTest : public testing::Test { | 80 class RenderTextTest : public testing::Test { |
63 }; | 81 }; |
64 | 82 |
65 TEST_F(RenderTextTest, DefaultStyle) { | 83 TEST_F(RenderTextTest, DefaultStyle) { |
66 // Check the default styles applied to new instances and adjusted text. | 84 // Check the default styles applied to new instances and adjusted text. |
67 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 85 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
68 EXPECT_TRUE(render_text->text().empty()); | 86 EXPECT_TRUE(render_text->text().empty()); |
69 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; | 87 const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" }; |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText()); | 384 EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText()); |
367 render_text->RenderText::SetObscuredRevealIndex(2); | 385 render_text->RenderText::SetObscuredRevealIndex(2); |
368 EXPECT_EQ(ASCIIToUTF16("*h***"), render_text->GetLayoutText()); | 386 EXPECT_EQ(ASCIIToUTF16("*h***"), render_text->GetLayoutText()); |
369 render_text->RenderText::SetObscuredRevealIndex(5); | 387 render_text->RenderText::SetObscuredRevealIndex(5); |
370 const char16 valid_expect_5_and_6[] = {'*', '*', '*', '*', 0xD800, 0xDC00, 0}; | 388 const char16 valid_expect_5_and_6[] = {'*', '*', '*', '*', 0xD800, 0xDC00, 0}; |
371 EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText()); | 389 EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText()); |
372 render_text->RenderText::SetObscuredRevealIndex(6); | 390 render_text->RenderText::SetObscuredRevealIndex(6); |
373 EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText()); | 391 EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText()); |
374 } | 392 } |
375 | 393 |
| 394 TEST_F(RenderTextTest, TruncatedText) { |
| 395 struct { |
| 396 const wchar_t* text; |
| 397 const wchar_t* layout_text; |
| 398 } cases[] = { |
| 399 // Strings shorter than the truncation length should be laid out in full. |
| 400 { L"", L"" }, |
| 401 { kWeak, kWeak }, |
| 402 { kLtr, kLtr }, |
| 403 { kLtrRtl, kLtrRtl }, |
| 404 { kLtrRtlLtr, kLtrRtlLtr }, |
| 405 { kRtl, kRtl }, |
| 406 { kRtlLtr, kRtlLtr }, |
| 407 { kRtlLtrRtl, kRtlLtrRtl }, |
| 408 // Strings as long as the truncation length should be laid out in full. |
| 409 { L"01234", L"01234" }, |
| 410 // Long strings should be truncated with an ellipsis appended at the end. |
| 411 { L"012345", L"0123\x2026" }, |
| 412 { L"012"L" . ", L"012 \x2026" }, |
| 413 { L"012"L"abc", L"012a\x2026" }, |
| 414 { L"012"L"a"L"\x5d0\x5d1", L"012a\x2026" }, |
| 415 { L"012"L"a"L"\x5d1"L"b", L"012a\x2026" }, |
| 416 { L"012"L"\x5d0\x5d1\x5d2", L"012\x5d0\x2026" }, |
| 417 { L"012"L"\x5d0\x5d1"L"a", L"012\x5d0\x2026" }, |
| 418 { L"012"L"\x5d0"L"a"L"\x5d1", L"012\x5d0\x2026" }, |
| 419 // Surrogate pairs should be truncated reasonably enough. |
| 420 { L"0123\x0915\x093f", L"0123\x2026" }, |
| 421 { L"0\x05e9\x05bc\x05c1\x05b8", L"0\x05e9\x05bc\x05c1\x05b8" }, |
| 422 { L"01\x05e9\x05bc\x05c1\x05b8", L"01\x05e9\x05bc\x2026" }, |
| 423 { L"012\x05e9\x05bc\x05c1\x05b8", L"012\x05e9\x2026" }, |
| 424 { L"0123\x05e9\x05bc\x05c1\x05b8", L"0123\x2026" }, |
| 425 { L"01234\x05e9\x05bc\x05c1\x05b8", L"0123\x2026" }, |
| 426 { L"012\xF0\x9D\x84\x9E", L"012\xF0\x2026" }, |
| 427 }; |
| 428 |
| 429 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 430 render_text->set_truncate_length(5); |
| 431 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { |
| 432 render_text->SetText(WideToUTF16(cases[i].text)); |
| 433 EXPECT_EQ(WideToUTF16(cases[i].text), render_text->text()); |
| 434 EXPECT_EQ(WideToUTF16(cases[i].layout_text), render_text->GetLayoutText()) |
| 435 << "For case " << i << ": " << cases[i].text; |
| 436 } |
| 437 } |
| 438 |
| 439 TEST_F(RenderTextTest, TruncatedObscuredText) { |
| 440 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 441 render_text->set_truncate_length(3); |
| 442 render_text->SetObscured(true); |
| 443 render_text->SetText(WideToUTF16(L"abcdef")); |
| 444 EXPECT_EQ(WideToUTF16(L"abcdef"), render_text->text()); |
| 445 EXPECT_EQ(WideToUTF16(L"**\x2026"), render_text->GetLayoutText()); |
| 446 } |
| 447 |
| 448 TEST_F(RenderTextTest, TruncatedCursorMovementLTR) { |
| 449 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 450 render_text->set_truncate_length(2); |
| 451 render_text->SetText(WideToUTF16(L"abcd")); |
| 452 |
| 453 EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); |
| 454 render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false); |
| 455 EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model()); |
| 456 render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false); |
| 457 EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); |
| 458 |
| 459 std::vector<SelectionModel> expected; |
| 460 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); |
| 461 expected.push_back(SelectionModel(1, CURSOR_BACKWARD)); |
| 462 expected.push_back(SelectionModel(2, CURSOR_BACKWARD)); |
| 463 // The cursor hops over the elided text to the line end. |
| 464 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 465 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 466 RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT); |
| 467 |
| 468 expected.clear(); |
| 469 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 470 // The cursor hops over the elided text to preceeding text. |
| 471 expected.push_back(SelectionModel(1, CURSOR_FORWARD)); |
| 472 expected.push_back(SelectionModel(0, CURSOR_FORWARD)); |
| 473 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); |
| 474 RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT); |
| 475 } |
| 476 |
| 477 TEST_F(RenderTextTest, TruncatedCursorMovementRTL) { |
| 478 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 479 render_text->set_truncate_length(2); |
| 480 render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3")); |
| 481 |
| 482 EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); |
| 483 render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false); |
| 484 EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model()); |
| 485 render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false); |
| 486 EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model()); |
| 487 |
| 488 std::vector<SelectionModel> expected; |
| 489 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); |
| 490 expected.push_back(SelectionModel(1, CURSOR_BACKWARD)); |
| 491 expected.push_back(SelectionModel(2, CURSOR_BACKWARD)); |
| 492 // The cursor hops over the elided text to the line end. |
| 493 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 494 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 495 RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT); |
| 496 |
| 497 expected.clear(); |
| 498 expected.push_back(SelectionModel(4, CURSOR_FORWARD)); |
| 499 // The cursor hops over the elided text to preceeding text. |
| 500 expected.push_back(SelectionModel(1, CURSOR_FORWARD)); |
| 501 expected.push_back(SelectionModel(0, CURSOR_FORWARD)); |
| 502 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); |
| 503 RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT); |
| 504 } |
| 505 |
376 TEST_F(RenderTextTest, GetTextDirection) { | 506 TEST_F(RenderTextTest, GetTextDirection) { |
377 struct { | 507 struct { |
378 const wchar_t* text; | 508 const wchar_t* text; |
379 const base::i18n::TextDirection text_direction; | 509 const base::i18n::TextDirection text_direction; |
380 } cases[] = { | 510 } cases[] = { |
381 // Blank strings and those with no/weak directionality default to LTR. | 511 // Blank strings and those with no/weak directionality default to LTR. |
382 { L"", base::i18n::LEFT_TO_RIGHT }, | 512 { L"", base::i18n::LEFT_TO_RIGHT }, |
383 { kWeak, base::i18n::LEFT_TO_RIGHT }, | 513 { kWeak, base::i18n::LEFT_TO_RIGHT }, |
384 // Strings that begin with strong LTR characters. | 514 // Strings that begin with strong LTR characters. |
385 { kLtr, base::i18n::LEFT_TO_RIGHT }, | 515 { kLtr, base::i18n::LEFT_TO_RIGHT }, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); | 547 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); |
418 | 548 |
419 // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT. | 549 // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT. |
420 render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT); | 550 render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT); |
421 render_text->SetText(WideToUTF16(kLtr)); | 551 render_text->SetText(WideToUTF16(kLtr)); |
422 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT); | 552 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT); |
423 render_text->SetText(WideToUTF16(kRtl)); | 553 render_text->SetText(WideToUTF16(kRtl)); |
424 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT); | 554 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT); |
425 } | 555 } |
426 | 556 |
427 void RunMoveCursorLeftRightTest(RenderText* render_text, | |
428 const std::vector<SelectionModel>& expected, | |
429 VisualCursorDirection direction) { | |
430 for (size_t i = 0; i < expected.size(); ++i) { | |
431 EXPECT_EQ(expected[i], render_text->selection_model()); | |
432 render_text->MoveCursor(CHARACTER_BREAK, direction, false); | |
433 } | |
434 // Check that cursoring is clamped at the line edge. | |
435 EXPECT_EQ(expected.back(), render_text->selection_model()); | |
436 // Check that it is the line edge. | |
437 render_text->MoveCursor(LINE_BREAK, direction, false); | |
438 EXPECT_EQ(expected.back(), render_text->selection_model()); | |
439 } | |
440 | |
441 TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) { | 557 TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) { |
442 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 558 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
443 | 559 |
444 // Pure LTR. | 560 // Pure LTR. |
445 render_text->SetText(ASCIIToUTF16("abc")); | 561 render_text->SetText(ASCIIToUTF16("abc")); |
446 // |expected| saves the expected SelectionModel when moving cursor from left | 562 // |expected| saves the expected SelectionModel when moving cursor from left |
447 // to right. | 563 // to right. |
448 std::vector<SelectionModel> expected; | 564 std::vector<SelectionModel> expected; |
449 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); | 565 expected.push_back(SelectionModel(0, CURSOR_BACKWARD)); |
450 expected.push_back(SelectionModel(1, CURSOR_BACKWARD)); | 566 expected.push_back(SelectionModel(1, CURSOR_BACKWARD)); |
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 EXPECT_EQ(render_text->display_rect().width() - width - 1, | 1511 EXPECT_EQ(render_text->display_rect().width() - width - 1, |
1396 render_text->GetUpdatedCursorBounds().x()); | 1512 render_text->GetUpdatedCursorBounds().x()); |
1397 | 1513 |
1398 // Reset the application default text direction to LTR. | 1514 // Reset the application default text direction to LTR. |
1399 SetRTL(was_rtl); | 1515 SetRTL(was_rtl); |
1400 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); | 1516 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); |
1401 } | 1517 } |
1402 #endif // !defined(OS_MACOSX) | 1518 #endif // !defined(OS_MACOSX) |
1403 | 1519 |
1404 } // namespace gfx | 1520 } // namespace gfx |
OLD | NEW |