render_text_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/render_text.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/break_list.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_LINUX)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/render_text_linux.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various weak, LTR, RTL, and Bidi string cases with three characters each.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kWeak[] =      L" . ";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kLtr[] =       L"abc";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kLtrRtl[] =    L"a"L"\x5d0\x5d1";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kLtrRtlLtr[] = L"a"L"\x5d1"L"b";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kRtl[] =       L"\x5d0\x5d1\x5d2";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kRtlLtr[] =    L"\x5d0\x5d1"L"a";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kRtlLtrRtl[] = L"\x5d0"L"a"L"\x5d1";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks whether |range| contains |index|. This is not the same as calling
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |range.Contains(ui::Range(index))| - as that would return true when
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |index| == |range.end()|.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IndexInRange(const ui::Range& range, size_t index) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return index >= range.start() && index < range.end();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::string16 GetSelectedText(RenderText* render_text) {
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return render_text->text().substr(render_text->selection().GetMin(),
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                    render_text->selection().length());
47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A test utility function to set the application default text direction.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetRTL(bool rtl) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override the current locale/direction.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the same for GTK, which does not rely on the ICU default locale.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_widget_set_default_direction(rtl ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(rtl, base::i18n::IsRTL());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderTextTest : public testing::Test {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DefaultStyle) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the default styles applied to new instances and adjusted text.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->text().empty());
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLACK));
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t style = 0; style < NUM_TEXT_STYLES; ++style)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[style].EqualsValueForTesting(false));
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, SetColorAndStyle) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure custom default styles persist across setting and clearing text.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkColor color = SK_ColorRED;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(color);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, true);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(UNDERLINE, false);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(color));
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(true));
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsValueForTesting(false));
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ensure custom default styles can be applied after text has been set.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i == 1)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_text->SetStyle(STRIKE, true);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i >= 1)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[STRIKE].EqualsValueForTesting(true));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, ApplyColorAndStyle) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a ranged color and style and check the resulting breaks.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, ui::Range(1, 4));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, ui::Range(2, 5));
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(0, SK_ColorBLACK));
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(1, SK_ColorRED));
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(4, SK_ColorBLACK));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color));
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(0, false));
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(2, true));
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(5, false));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure setting a color and style overrides the ranged colors and styles.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(SK_ColorBLUE);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLUE));
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, false);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(false));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a color and style over the text end and check the resulting breaks.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (INT_MAX should be used instead of the text length for the range end)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t text_length = render_text->text().length();
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, ui::Range(0, text_length));
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, ui::Range(2, text_length));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color_end;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color_end.push_back(std::pair<size_t, SkColor>(0, SK_ColorRED));
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color_end));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style_end;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(0, false));
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(2, true));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style_end));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure ranged values adjust to accommodate text length changes.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, ui::Range(0, 2));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, ui::Range(3, 6));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, ui::Range(7, text_length));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_italic;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(0, true));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(2, false));
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(3, true));
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(6, false));
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(7, true));
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Truncating the text should trim any corresponding breaks.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("0123456"));
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.resize(4);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("01234"));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.resize(3);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Appending text should extend the terminal styles without changing breaks.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_LINUX)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, PangoAttributes) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply ranged BOLD/ITALIC styles and check the resulting Pango attributes.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, ui::Range(2, 4));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, ui::Range(1, 3));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int start;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int end;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool bold;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool italic;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } cases[] = {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 0, 1,       false, false },
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 1, 2,       false, true  },
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 2, 3,       true,  true  },
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 3, 4,       true,  false },
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 4, INT_MAX, false, false },
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int start = 0, end = 0;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderTextLinux* rt_linux = static_cast<RenderTextLinux*>(render_text.get());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rt_linux->EnsureLayout();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrList* attributes = pango_layout_get_attributes(rt_linux->layout_);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrIterator* iter = pango_attr_list_get_iterator(attributes);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_range(iter, &start, &end);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].start, start);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].end, end);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PangoFontDescription* font = pango_font_description_new();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_get_font(iter, font, NULL, NULL);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* description_string = pango_font_description_to_string(font);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string16 desc = ASCIIToUTF16(description_string);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool bold = desc.find(ASCIIToUTF16("Bold")) != std::string::npos;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].bold, bold);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool italic = desc.find(ASCIIToUTF16("Italic")) != std::string::npos;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].italic, italic);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_next(iter);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_font_description_free(font);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_free(description_string);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pango_attr_iterator_next(iter));
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pango_attr_iterator_destroy(iter);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVisualCursorMotionInObscuredField(RenderText* render_text,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const string16& text,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool select) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(render_text->obscured());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(text);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = text.length();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : len, len), CURSOR_FORWARD),
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, select);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 1; j <= len; ++j) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, select);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : j, j), CURSOR_BACKWARD),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = len - 1; j >= 0; --j) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, select);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : j, j), CURSOR_FORWARD),
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, select);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(ui::Range(select ? 0 : len, len), CURSOR_FORWARD),
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, select);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, ObscuredText) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 seuss = ASCIIToUTF16("hop on pop");
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 no_seuss = ASCIIToUTF16("**********");
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetLayoutText() returns asterisks when the obscured bit is set.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(seuss);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(false);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->GetLayoutText());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Surrogate pairs are counted as one code point.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char16 invalid_surrogates[] = {0xDC00, 0xD800, 0};
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(invalid_surrogates);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**"), render_text->GetLayoutText());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char16 valid_surrogates[] = {0xD800, 0xDC00, 0};
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(valid_surrogates);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*"), render_text->GetLayoutText());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test index conversion and cursor validity with a valid surrogate pair.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->TextIndexToLayoutIndex(0U));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(1U));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(2U));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->LayoutIndexToTextIndex(0U));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->LayoutIndexToTextIndex(1U));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->IsCursorablePosition(0U));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(render_text->IsCursorablePosition(1U));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->IsCursorablePosition(2U));
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindCursorPosition() should not return positions between a surrogate pair.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 20, 20));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(0, 0)).caret_pos(), 0U);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(20, 0)).caret_pos(), 2U);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int x = -1; x <= 20; ++x) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel selection = render_text->FindCursorPosition(Point(x, 0));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(selection.caret_pos() == 0U || selection.caret_pos() == 2U);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetGlyphBounds() should yield the entire string bounds for text index 0.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetStringSize().width(),
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            static_cast<int>(render_text->GetGlyphBounds(0U).length()));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cursoring is independent of underlying characters when text is obscured.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const texts[] = {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"hop on pop",                              // Check LTR word boundaries.
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"\x05d0\x05d1 \x05d0\x05d2 \x05d1\x05d2",  // Check RTL word boundaries.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(texts); ++i) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 text = WideToUTF16(texts[i]);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, false);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, true);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetTextDirection) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* text;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection text_direction;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Blank strings and those with no/weak directionality default to LTR.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { L"",        base::i18n::LEFT_TO_RIGHT },
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kWeak,      base::i18n::LEFT_TO_RIGHT },
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong LTR characters.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtr,       base::i18n::LEFT_TO_RIGHT },
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtl,    base::i18n::LEFT_TO_RIGHT },
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtlLtr, base::i18n::LEFT_TO_RIGHT },
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong RTL characters.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtl,       base::i18n::RIGHT_TO_LEFT },
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtr,    base::i18n::RIGHT_TO_LEFT },
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtrRtl, base::i18n::RIGHT_TO_LEFT },
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Toggle the application default text direction (to try each direction).
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection ui_direction = base::i18n::IsRTL() ?
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that directionality modes yield the correct text directions.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j].text));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), cases[j].text_direction);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), ui_direction);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_RTL);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kLtr));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kRtl));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunMoveCursorLeftRightTest(RenderText* render_text,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<SelectionModel>& expected,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VisualCursorDirection direction) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < expected.size(); ++i) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected[i], render_text->selection_model());
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, direction, false);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that cursoring is clamped at the line edge.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected.back(), render_text->selection_model());
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that it is the line edge.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, direction, false);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected.back(), render_text->selection_model());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure LTR.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abc"));
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |expected| saves the expected SelectionModel when moving cursor from left
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to right.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtl) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last one is the expected END position.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtlLtr) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL-LTR.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"a"L"\x05d1"L"b"));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtl) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure RTL.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtr) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"L"abc"));
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtrRtl) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR-RTL.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05d0"L"a"L"\x05d1"));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): temporarily disable in platform Win since the complex script
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// characters turned into empty square due to font regression. So, not able
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test 2 characters belong to the same grapheme.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GraphemePositions) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR abc, LTR 2-character grapheme.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kText1 = WideToUTF16(L"\x0915\x093f"L"abc"L"\x0915\x093f");
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, LTR 2-character grapheme, LTR cd.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kText2 = WideToUTF16(L"ab"L"\x0915\x093f"L"cd");
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // two characters forming the surrogate pair 0x0001D11E.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSurrogate = "\xF0\x9D\x84\x9E";
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, UTF16 surrogate pair, LTR cd.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kText3 = UTF8ToUTF16("ab" + kSurrogate + "cd");
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 text;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t index;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_previous;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_next;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { string16(), 0, 0, 0 },
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { string16(), 1, 0, 0 },
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { string16(), 50, 0, 0 },
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 0, 0, 2 },
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 1, 0, 2 },
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 2, 0, 3 },
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 3, 2, 4 },
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 4, 3, 5 },
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 5, 4, 7 },
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 6, 5, 7 },
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 7, 5, 7 },
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 8, 7, 7 },
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 50, 7, 7 },
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 0, 0, 1 },
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 1, 0, 2 },
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 2, 1, 4 },
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 3, 2, 4 },
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 4, 2, 5 },
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 5, 4, 6 },
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 6, 5, 6 },
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 7, 6, 6 },
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 50, 6, 6 },
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 0, 0, 1 },
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 1, 0, 2 },
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 2, 1, 4 },
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 3, 2, 4 },
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 4, 2, 5 },
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 5, 4, 6 },
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 6, 5, 6 },
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 7, 6, 6 },
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 50, 6, 6 },
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                  font support for some scripts - http://crbug.com/106450
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t next = render_text->IndexOfAdjacentGrapheme(cases[i].index,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       CURSOR_FORWARD);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_next, next);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(render_text->IsCursorablePosition(next));
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t previous = render_text->IndexOfAdjacentGrapheme(cases[i].index,
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           CURSOR_BACKWARD);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_previous, previous);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(render_text->IsCursorablePosition(previous));
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, EdgeSelectionModels) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simple Latin text.
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kLatin = WideToUTF16(L"abc");
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f");
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR a, LTR 2-character grapheme.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kHindiLatin = WideToUTF16(L"\x0915\x093f"L"a"L"\x0915\x093f");
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kRTLGrapheme = WideToUTF16(L"\x05e0\x05b8");
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme, LTR a, RTL 2-character grapheme.
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16 kHebrewLatin = WideToUTF16(L"\x05e0\x05b8"L"a"L"\x05e0\x05b8");
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 text;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::i18n::TextDirection expected_text_direction;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { string16(),   base::i18n::LEFT_TO_RIGHT },
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLatin,       base::i18n::LEFT_TO_RIGHT },
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLTRGrapheme, base::i18n::LEFT_TO_RIGHT },
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHindiLatin,  base::i18n::LEFT_TO_RIGHT },
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRTLGrapheme, base::i18n::RIGHT_TO_LEFT },
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHebrewLatin, base::i18n::RIGHT_TO_LEFT },
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                  font support for some scripts - http://crbug.com/106450
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ltr = (cases[i].expected_text_direction == base::i18n::LEFT_TO_RIGHT);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start_edge =
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_LEFT : CURSOR_RIGHT);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(start_edge, SelectionModel(0, CURSOR_BACKWARD));
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end_edge =
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_RIGHT : CURSOR_LEFT);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end_edge, SelectionModel(cases[i].text.length(), CURSOR_FORWARD));
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SelectAll) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const cases[] =
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl };
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that SelectAll respects the |reversed| argument regardless of
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // application locale and text content directionality.
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SelectionModel expected_reversed(ui::Range(3, 0), CURSOR_FORWARD);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SelectionModel expected_forwards(ui::Range(0, 3), CURSOR_BACKWARD);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test that an empty string produces an empty selection model.
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(string16());
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(render_text->selection_model(), SelectionModel());
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the weak, LTR, RTL, and Bidi string cases.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j]));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(false);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_forwards);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(true);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_reversed);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Left arrow on select ranging (6, 4).
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(6), render_text->selection());
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(4), render_text->selection());
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(5), render_text->selection());
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(6), render_text->selection());
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(6, 5), render_text->selection());
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(6, 4), render_text->selection());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(6), render_text->selection());
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Right arrow on select ranging (4, 6).
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(0), render_text->selection());
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(1), render_text->selection());
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(2), render_text->selection());
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(3), render_text->selection());
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(5), render_text->selection());
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(4), render_text->selection());
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(4, 5), render_text->selection());
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(4, 6), render_text->selection());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::Range(4), render_text->selection());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): Make these work on Windows.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MoveLeftRightByWordVerifier(RenderText* render_text,
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const wchar_t* str) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(str));
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from left ro right.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first_word = true;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, test moving by word from a word break position, such as from
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "|abc def" to "abc| def".
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For testing simplicity, each word is a 3-character word.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then, test moving by word from positions inside the word, such as from
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "a|bc def" to "abc| def", and from "ab|c def" to "abc| def".
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from right to left.
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_word = true;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For testing simplicity, each word is a 3-character word.
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const wchar_t*> test;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc");
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def");
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3");
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3");
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3 hij");
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 hij opq");
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9"L" opq rst uvw");
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 abc");
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 abc def");
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 \x05E7\x05E8\x05E9"
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij");
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 abc \x05E1\x05E2\x05E3");
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 abc def"
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 \x05D7\x05D8\x05D9"
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test.size(); ++i)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MoveLeftRightByWordVerifier(render_text.get(), test[i]);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"ab\x05E1"));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "abC|" to the left should return "|abC".
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "ab|C".
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|abC" to the right returns "abC|".
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05E1\x05E2"L"a"));
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For logical text "BCa", moving the cursor by word from "aCB|" to the left
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns "|aCB".
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|aCB" to the right should return "aCB|".
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "a|CB".
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc     def"));
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(11U, render_text->cursor_position());
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x6211\x4EEC\x53BB\x516C\x56ED\x73A9"));
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, render_text->cursor_position());
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeSanity) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Size string_size = render_text->GetStringSize();
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.width(), 0);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.height(), 0);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): This test fails because PlatformFontMac uses point font
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  sizes instead of pixel sizes like other implementations.
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeEmptyString) {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Font font;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFont(font);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(string16());
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(font.GetHeight(), render_text->GetStringSize().height());
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetStringSize().width());
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16(" "));
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(font.GetHeight(), render_text->GetStringSize().height());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SetFont) {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFont(Font("Arial", 12));
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("Arial", render_text->GetFont().GetFontName());
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(12, render_text->GetFont().GetFontSize());
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeBoldWidth) {
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_width = render_text->GetStringSize().width();
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_width, 0);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply a bold style and check that the new width is greater.
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(gfx::BOLD, true);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bold_width = render_text->GetStringSize().width();
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(bold_width, plain_width);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, apply a plain style over the first word only.
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->ApplyStyle(gfx::BOLD, false, ui::Range(0, 5));
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_bold_width = render_text->GetStringSize().width();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_bold_width, plain_width);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(plain_bold_width, bold_width);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeHeight) {
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  string16 cases[] = {
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"Hello World!"),  // English
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x6328\x62f6"),  // Japanese
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x0915\x093f"),  // Hindi
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x05e0\x05b8"),  // Hebrew
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font default_font;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font larger_font = default_font.DeriveFont(24, default_font.GetStyle());
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(larger_font.GetHeight(), default_font.GetHeight());
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetFont(default_font);
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(cases[i]);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height1 = render_text->GetStringSize().height();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height1, 0);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that setting the larger font increases the height.
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetFont(larger_font);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height2 = render_text->GetStringSize().height();
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height2, height1);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetBaselineSanity) {
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int baseline = render_text->GetBaseline();
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(baseline, 0);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, CursorBoundsInReplacementMode) {
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(100, 17));
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_b(1, CURSOR_FORWARD);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_c(2, CURSOR_FORWARD);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_around_b = render_text->GetCursorBounds(sel_b, false);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_b = render_text->GetCursorBounds(sel_b, true);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_c = render_text->GetCursorBounds(sel_c, true);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.x(), cursor_before_b.x());
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.right(), cursor_before_c.x());
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffset) {
99990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The default horizontal text offset differs for LTR and RTL, and is only set
100090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // when the RenderText object is created.  This test will check the default in
100190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // LTR mode, and the next test will check the RTL default.
100290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
100390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(false);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set display area's size equal to the font size.
100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const gfx::Size font_size(render_text->GetContentWidth(),
101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            render_text->GetStringSize().height());
101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Vector2d offset = render_text->GetTextOffset();
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(offset.IsZero());
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set display area's size greater than font size.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kEnlargement = 2;
101990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  display_rect.Inset(0, 0, -kEnlargement, -kEnlargement);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check the default horizontal and vertical alignment.
102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.y());
102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
102790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check explicitly setting the horizontal alignment.
102890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_LEFT);
102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
103090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
103190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_CENTER);
103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.x());
103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_RIGHT);
103590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.x());
103790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check explicitly setting the vertical alignment.
103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_TOP);
104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
104190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.y());
104290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_VCENTER);
104390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
104490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.y());
104590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_BOTTOM);
104690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  offset = render_text->GetTextOffset();
104790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.y());
104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
105090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
105190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
105290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) {
105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This only checks the default horizontal alignment in RTL mode; all other
105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // GetTextOffset() attributes are checked by the test above.
105590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
105690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(true);
105790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
105890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
105990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kEnlargement = 2;
106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const gfx::Size font_size(render_text->GetContentWidth() + kEnlargement,
106290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            render_text->GetStringSize().height());
106390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
106490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
106590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Vector2d offset = render_text->GetTextOffset();
106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.x());
106790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SameFontForParentheses) {
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char16 left_char;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char16 right_char;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } punctuation_pairs[] = {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '(', ')' },
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '{', '}' },
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '<', '>' },
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 text;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)") },
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)English
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)Hello World") },
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)") },
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)Japanese
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)\x6328\x62f6") },
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Japanese)English
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x6328\x62f6)Hello World") },
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)") },
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)Hindi
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)\x0915\x093f") },
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hindi)English
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x0915\x093f)Hello World") },
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)") },
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)Hebrew
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)\x05e0\x05b8") },
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hebrew)English
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x05e0\x05b8)Hello World") },
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string16 text = cases[i].text;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t start_paren_char_index = text.find('(');
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(string16::npos, start_paren_char_index);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t end_paren_char_index = text.find(')');
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(string16::npos, end_paren_char_index);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(punctuation_pairs); ++j) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[start_paren_char_index] = punctuation_pairs[j].left_char;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[end_paren_char_index] = punctuation_pairs[j].right_char;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(text);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<RenderText::FontSpan> spans =
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          render_text->GetFontSpansForTesting();
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int start_paren_span_index = -1;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int end_paren_span_index = -1;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t k = 0; k < spans.size(); ++k) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, start_paren_char_index))
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start_paren_span_index = k;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, end_paren_char_index))
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          end_paren_span_index = k;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, start_paren_span_index);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, end_paren_span_index);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& start_font = spans[start_paren_span_index].first;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& end_font = spans[end_paren_span_index].first;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontName(), end_font.GetFontName());
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontSize(), end_font.GetFontSize());
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetStyle(), end_font.GetStyle());
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure the caret width is always >=1 so that the correct
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// caret is drawn at high DPI. crbug.com/164100.
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, CaretWidth) {
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_GE(render_text->GetUpdatedCursorBounds().width(), 1);
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Make sure the last word is selected when the cursor is at text.length().
1154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(RenderTextTest, LastWordSelected) {
1155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL1 = "http://www.google.com";
1156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL2 = "http://www.google.com/something/";
1157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL1));
1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL1.length());
1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("com"), GetSelectedText(render_text.get()));
1164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL2));
1167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL2.length());
1168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("/"), GetSelectedText(render_text.get()));
1170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
1172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// When given a non-empty selection, SelectWord should expand the selection to
1174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// nearest word boundaries.
1175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)TEST_F(RenderTextTest, SelectMultipleWords) {
1176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string kTestURL = "http://www.google.com";
1177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL));
1181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectRange(ui::Range(16, 20));
1182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // SelectWord should preserve the selection direction.
1187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectRange(ui::Range(20, 16));
1188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1190a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(render_text->selection().is_reversed());
1191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorLTR) {
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::IsRTL());
11982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::ICUIsRTL());
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - 1,
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(msw): Investigate why this test passes with
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |GetUpdateCursorBounds().x()|, while the above have to use
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |.right()|.
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - 1,
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - 1,
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - 1,
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) {
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the application default text direction to RTL.
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(true);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the application default text direction to LTR.
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(was_rtl);
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
1316