| 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/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "ui/base/l10n/l10n_util.h" | 10 #include "ui/base/l10n/l10n_util.h" |
| 11 #include "ui/gfx/text_constants.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(TOOLKIT_GTK) | 17 #if defined(TOOLKIT_GTK) |
| 17 #include <gtk/gtk.h> | 18 #include <gtk/gtk.h> |
| 18 #endif | 19 #endif |
| 19 | 20 |
| 20 namespace gfx { | 21 namespace gfx { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 25 // Various weak, LTR, RTL, and Bidi string cases with three characters each. |
| 26 const wchar_t kWeak[] = L" . "; |
| 27 const wchar_t kLtr[] = L"abc"; |
| 28 const wchar_t kLtrRtl[] = L"a"L"\x5d0\x5d1"; |
| 29 const wchar_t kLtrRtlLtr[] = L"a"L"\x5d1"L"b"; |
| 30 const wchar_t kRtl[] = L"\x5d0\x5d1\x5d2"; |
| 31 const wchar_t kRtlLtr[] = L"\x5d0\x5d1"L"a"; |
| 32 const wchar_t kRtlLtrRtl[] = L"\x5d0"L"a"L"\x5d1"; |
| 33 |
| 24 // Checks whether |range| contains |index|. This is not the same as calling | 34 // Checks whether |range| contains |index|. This is not the same as calling |
| 25 // |range.Contains(ui::Range(index))| - as that would return true when | 35 // |range.Contains(ui::Range(index))| - as that would return true when |
| 26 // |index| == |range.end()|. | 36 // |index| == |range.end()|. |
| 27 bool IndexInRange(const ui::Range& range, size_t index) { | 37 bool IndexInRange(const ui::Range& range, size_t index) { |
| 28 return index >= range.start() && index < range.end(); | 38 return index >= range.start() && index < range.end(); |
| 29 } | 39 } |
| 30 | 40 |
| 31 // A test utility function to set the application default text direction. | 41 // A test utility function to set the application default text direction. |
| 32 void SetRTL(bool rtl) { | 42 void SetRTL(bool rtl) { |
| 33 // Override the current locale/direction. | 43 // Override the current locale/direction. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 EXPECT_EQ(ui::Range(2, 10), render_text->style_ranges()[1].range); | 222 EXPECT_EQ(ui::Range(2, 10), render_text->style_ranges()[1].range); |
| 213 EXPECT_EQ(SK_ColorRED, render_text->style_ranges()[1].foreground); | 223 EXPECT_EQ(SK_ColorRED, render_text->style_ranges()[1].foreground); |
| 214 EXPECT_EQ(ui::Range(10, 12), render_text->style_ranges()[2].range); | 224 EXPECT_EQ(ui::Range(10, 12), render_text->style_ranges()[2].range); |
| 215 EXPECT_TRUE(render_text->style_ranges()[2].underline); | 225 EXPECT_TRUE(render_text->style_ranges()[2].underline); |
| 216 EXPECT_TRUE(render_text->style_ranges()[2].strike); | 226 EXPECT_TRUE(render_text->style_ranges()[2].strike); |
| 217 } | 227 } |
| 218 | 228 |
| 219 static void SetTextWith2ExtraStyles(RenderText* render_text) { | 229 static void SetTextWith2ExtraStyles(RenderText* render_text) { |
| 220 render_text->SetText(ASCIIToUTF16("abcdefghi")); | 230 render_text->SetText(ASCIIToUTF16("abcdefghi")); |
| 221 | 231 |
| 222 gfx::StyleRange strike; | 232 StyleRange strike; |
| 223 strike.strike = true; | 233 strike.strike = true; |
| 224 strike.range = ui::Range(0, 3); | 234 strike.range = ui::Range(0, 3); |
| 225 render_text->ApplyStyleRange(strike); | 235 render_text->ApplyStyleRange(strike); |
| 226 | 236 |
| 227 gfx::StyleRange underline; | 237 StyleRange underline; |
| 228 underline.underline = true; | 238 underline.underline = true; |
| 229 underline.range = ui::Range(3, 6); | 239 underline.range = ui::Range(3, 6); |
| 230 render_text->ApplyStyleRange(underline); | 240 render_text->ApplyStyleRange(underline); |
| 231 } | 241 } |
| 232 | 242 |
| 233 TEST_F(RenderTextTest, StyleRangesAdjust) { | 243 TEST_F(RenderTextTest, StyleRangesAdjust) { |
| 234 // Test that style ranges adjust to the text size. | 244 // Test that style ranges adjust to the text size. |
| 235 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 245 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 236 render_text->SetText(ASCIIToUTF16("abcdef")); | 246 render_text->SetText(ASCIIToUTF16("abcdef")); |
| 237 EXPECT_EQ(1U, render_text->style_ranges().size()); | 247 EXPECT_EQ(1U, render_text->style_ranges().size()); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 }; | 386 }; |
| 377 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(texts); ++i) { | 387 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(texts); ++i) { |
| 378 string16 text = WideToUTF16(texts[i]); | 388 string16 text = WideToUTF16(texts[i]); |
| 379 TestVisualCursorMotionInObscuredField(render_text.get(), text, false); | 389 TestVisualCursorMotionInObscuredField(render_text.get(), text, false); |
| 380 TestVisualCursorMotionInObscuredField(render_text.get(), text, true); | 390 TestVisualCursorMotionInObscuredField(render_text.get(), text, true); |
| 381 } | 391 } |
| 382 #endif // !defined(OS_WIN) | 392 #endif // !defined(OS_WIN) |
| 383 } | 393 } |
| 384 | 394 |
| 385 TEST_F(RenderTextTest, GetTextDirection) { | 395 TEST_F(RenderTextTest, GetTextDirection) { |
| 396 struct { |
| 397 const wchar_t* text; |
| 398 const base::i18n::TextDirection text_direction; |
| 399 } cases[] = { |
| 400 // Blank strings and those with no/weak directionality default to LTR. |
| 401 { L"", base::i18n::LEFT_TO_RIGHT }, |
| 402 { kWeak, base::i18n::LEFT_TO_RIGHT }, |
| 403 // Strings that begin with strong LTR characters. |
| 404 { kLtr, base::i18n::LEFT_TO_RIGHT }, |
| 405 { kLtrRtl, base::i18n::LEFT_TO_RIGHT }, |
| 406 { kLtrRtlLtr, base::i18n::LEFT_TO_RIGHT }, |
| 407 // Strings that begin with strong RTL characters. |
| 408 { kRtl, base::i18n::RIGHT_TO_LEFT }, |
| 409 { kRtlLtr, base::i18n::RIGHT_TO_LEFT }, |
| 410 { kRtlLtrRtl, base::i18n::RIGHT_TO_LEFT }, |
| 411 }; |
| 412 |
| 413 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 386 const bool was_rtl = base::i18n::IsRTL(); | 414 const bool was_rtl = base::i18n::IsRTL(); |
| 387 // Ensure that text direction is set by the first strong character direction. | 415 |
| 388 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | |
| 389 for (size_t i = 0; i < 2; ++i) { | 416 for (size_t i = 0; i < 2; ++i) { |
| 390 // Toggle the application default text direction (to try each direction). | 417 // Toggle the application default text direction (to try each direction). |
| 391 SetRTL(!base::i18n::IsRTL()); | 418 SetRTL(!base::i18n::IsRTL()); |
| 419 const base::i18n::TextDirection ui_direction = base::i18n::IsRTL() ? |
| 420 base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT; |
| 392 | 421 |
| 393 // Blank strings (and those without directionality) default to LTR. | 422 // Ensure that directionality modes yield the correct text directions. |
| 394 render_text->SetText(string16()); | 423 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) { |
| 395 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); | 424 render_text->SetText(WideToUTF16(cases[j].text)); |
| 396 render_text->SetText(ASCIIToUTF16(" ")); | 425 render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT); |
| 397 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); | 426 EXPECT_EQ(render_text->GetTextDirection(), cases[j].text_direction); |
| 427 render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI); |
| 428 EXPECT_EQ(render_text->GetTextDirection(), ui_direction); |
| 429 render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR); |
| 430 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT); |
| 431 render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_RTL); |
| 432 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT); |
| 433 } |
| 434 } |
| 398 | 435 |
| 399 // Pure LTR. | |
| 400 render_text->SetText(ASCIIToUTF16("abc")); | |
| 401 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); | |
| 402 // LTR-RTL | |
| 403 render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2")); | |
| 404 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); | |
| 405 // LTR-RTL-LTR. | |
| 406 render_text->SetText(WideToUTF16(L"a"L"\x05d1"L"b")); | |
| 407 EXPECT_EQ(base::i18n::LEFT_TO_RIGHT, render_text->GetTextDirection()); | |
| 408 // Pure RTL. | |
| 409 render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2")); | |
| 410 EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection()); | |
| 411 // RTL-LTR | |
| 412 render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"L"abc")); | |
| 413 EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection()); | |
| 414 // RTL-LTR-RTL. | |
| 415 render_text->SetText(WideToUTF16(L"\x05d0"L"a"L"\x05d1")); | |
| 416 EXPECT_EQ(base::i18n::RIGHT_TO_LEFT, render_text->GetTextDirection()); | |
| 417 } | |
| 418 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); | 436 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); |
| 437 |
| 438 // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT. |
| 439 render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT); |
| 440 render_text->SetText(WideToUTF16(kLtr)); |
| 441 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT); |
| 442 render_text->SetText(WideToUTF16(kRtl)); |
| 443 EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT); |
| 419 } | 444 } |
| 420 | 445 |
| 421 void RunMoveCursorLeftRightTest(RenderText* render_text, | 446 void RunMoveCursorLeftRightTest(RenderText* render_text, |
| 422 const std::vector<SelectionModel>& expected, | 447 const std::vector<SelectionModel>& expected, |
| 423 VisualCursorDirection direction) { | 448 VisualCursorDirection direction) { |
| 424 for (size_t i = 0; i < expected.size(); ++i) { | 449 for (size_t i = 0; i < expected.size(); ++i) { |
| 425 EXPECT_EQ(expected[i], render_text->selection_model()); | 450 EXPECT_EQ(expected[i], render_text->selection_model()); |
| 426 render_text->MoveCursor(CHARACTER_BREAK, direction, false); | 451 render_text->MoveCursor(CHARACTER_BREAK, direction, false); |
| 427 } | 452 } |
| 428 // Check that cursoring is clamped at the line edge. | 453 // Check that cursoring is clamped at the line edge. |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 render_text->EdgeSelectionModel(ltr ? CURSOR_LEFT : CURSOR_RIGHT); | 749 render_text->EdgeSelectionModel(ltr ? CURSOR_LEFT : CURSOR_RIGHT); |
| 725 EXPECT_EQ(start_edge, SelectionModel(0, CURSOR_BACKWARD)); | 750 EXPECT_EQ(start_edge, SelectionModel(0, CURSOR_BACKWARD)); |
| 726 | 751 |
| 727 SelectionModel end_edge = | 752 SelectionModel end_edge = |
| 728 render_text->EdgeSelectionModel(ltr ? CURSOR_RIGHT : CURSOR_LEFT); | 753 render_text->EdgeSelectionModel(ltr ? CURSOR_RIGHT : CURSOR_LEFT); |
| 729 EXPECT_EQ(end_edge, SelectionModel(cases[i].text.length(), CURSOR_FORWARD)); | 754 EXPECT_EQ(end_edge, SelectionModel(cases[i].text.length(), CURSOR_FORWARD)); |
| 730 } | 755 } |
| 731 } | 756 } |
| 732 | 757 |
| 733 TEST_F(RenderTextTest, SelectAll) { | 758 TEST_F(RenderTextTest, SelectAll) { |
| 734 const wchar_t* const cases[] = { | 759 const wchar_t* const cases[] = |
| 735 L"abc", | 760 { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl }; |
| 736 L"a"L"\x5d0\x5d1", | |
| 737 L"a"L"\x5d1"L"b", | |
| 738 L"\x5d0\x5d1\x5d2", | |
| 739 L"\x5d0\x5d1"L"a", | |
| 740 L"\x5d0"L"a"L"\x5d1", | |
| 741 }; | |
| 742 | 761 |
| 743 // Ensure that SelectAll respects the |reversed| argument regardless of | 762 // Ensure that SelectAll respects the |reversed| argument regardless of |
| 744 // application locale and text content directionality. | 763 // application locale and text content directionality. |
| 745 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); | 764 scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); |
| 746 const SelectionModel expected_reversed(ui::Range(3, 0), CURSOR_FORWARD); | 765 const SelectionModel expected_reversed(ui::Range(3, 0), CURSOR_FORWARD); |
| 747 const SelectionModel expected_forwards(ui::Range(0, 3), CURSOR_BACKWARD); | 766 const SelectionModel expected_forwards(ui::Range(0, 3), CURSOR_BACKWARD); |
| 748 const bool was_rtl = base::i18n::IsRTL(); | 767 const bool was_rtl = base::i18n::IsRTL(); |
| 749 | 768 |
| 750 for (size_t i = 0; i < 2; ++i) { | 769 for (size_t i = 0; i < 2; ++i) { |
| 751 SetRTL(!base::i18n::IsRTL()); | 770 SetRTL(!base::i18n::IsRTL()); |
| 771 // Test that an empty string produces an empty selection model. |
| 772 render_text->SetText(string16()); |
| 773 EXPECT_EQ(render_text->selection_model(), SelectionModel()); |
| 774 |
| 775 // Test the weak, LTR, RTL, and Bidi string cases. |
| 752 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) { | 776 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) { |
| 753 render_text->SetText(WideToUTF16(cases[j])); | 777 render_text->SetText(WideToUTF16(cases[j])); |
| 754 render_text->SelectAll(false); | 778 render_text->SelectAll(false); |
| 755 EXPECT_EQ(render_text->selection_model(), expected_forwards); | 779 EXPECT_EQ(render_text->selection_model(), expected_forwards); |
| 756 render_text->SelectAll(true); | 780 render_text->SelectAll(true); |
| 757 EXPECT_EQ(render_text->selection_model(), expected_reversed); | 781 EXPECT_EQ(render_text->selection_model(), expected_reversed); |
| 758 } | 782 } |
| 759 } | 783 } |
| 760 | 784 |
| 761 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); | 785 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 EXPECT_EQ(render_text->display_rect().width() - width - 1, | 1297 EXPECT_EQ(render_text->display_rect().width() - width - 1, |
| 1274 render_text->GetUpdatedCursorBounds().x()); | 1298 render_text->GetUpdatedCursorBounds().x()); |
| 1275 | 1299 |
| 1276 // Reset the application default text direction to LTR. | 1300 // Reset the application default text direction to LTR. |
| 1277 SetRTL(was_rtl); | 1301 SetRTL(was_rtl); |
| 1278 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); | 1302 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); |
| 1279 } | 1303 } |
| 1280 #endif // !defined(OS_MACOSX) | 1304 #endif // !defined(OS_MACOSX) |
| 1281 | 1305 |
| 1282 } // namespace gfx | 1306 } // namespace gfx |
| OLD | NEW |