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 |