render_text_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <algorithm>
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/format_macros.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/break_list.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/gfx/canvas.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/gfx/render_text_win.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_LINUX)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/render_text_linux.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various weak, LTR, RTL, and Bidi string cases with three characters each.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kWeak[] =      L" . ";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kLtr[] =       L"abc";
37bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kLtrRtl[] =    L"a" L"\x5d0\x5d1";
38bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kLtrRtlLtr[] = L"a" L"\x5d1" L"b";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kRtl[] =       L"\x5d0\x5d1\x5d2";
40bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kRtlLtr[] =    L"\x5d0\x5d1" L"a";
41bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1";
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks whether |range| contains |index|. This is not the same as calling
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// |range.Contains(gfx::Range(index))| - as that would return true when
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |index| == |range.end()|.
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool IndexInRange(const Range& range, size_t index) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return index >= range.start() && index < range.end();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::string16 GetSelectedText(RenderText* render_text) {
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return render_text->text().substr(render_text->selection().GetMin(),
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                    render_text->selection().length());
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A test utility function to set the application default text direction.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetRTL(bool rtl) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override the current locale/direction.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do the same for GTK, which does not rely on the ICU default locale.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gtk_widget_set_default_direction(rtl ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(rtl, base::i18n::IsRTL());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Ensure cursor movement in the specified |direction| yields |expected| values.
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RunMoveCursorLeftRightTest(RenderText* render_text,
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                const std::vector<SelectionModel>& expected,
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                VisualCursorDirection direction) {
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < expected.size(); ++i) {
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SCOPED_TRACE(base::StringPrintf("Going %s; expected value index %d.",
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        direction == CURSOR_LEFT ? "left" : "right", static_cast<int>(i)));
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(expected[i], render_text->selection_model());
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    render_text->MoveCursor(CHARACTER_BREAK, direction, false);
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that cursoring is clamped at the line edge.
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected.back(), render_text->selection_model());
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that it is the line edge.
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, direction, false);
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected.back(), render_text->selection_model());
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderTextTest : public testing::Test {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DefaultStyle) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the default styles applied to new instances and adjusted text.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->text().empty());
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLACK));
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t style = 0; style < NUM_TEXT_STYLES; ++style)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[style].EqualsValueForTesting(false));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, SetColorAndStyle) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure custom default styles persist across setting and clearing text.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkColor color = SK_ColorRED;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(color);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, true);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(UNDERLINE, false);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(color));
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(true));
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsValueForTesting(false));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ensure custom default styles can be applied after text has been set.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i == 1)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_text->SetStyle(STRIKE, true);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i >= 1)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[STRIKE].EqualsValueForTesting(true));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, ApplyColorAndStyle) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a ranged color and style and check the resulting breaks.
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, Range(1, 4));
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, 5));
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(0, SK_ColorBLACK));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(1, SK_ColorRED));
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(4, SK_ColorBLACK));
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(0, false));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(2, true));
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(5, false));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure setting a color and style overrides the ranged colors and styles.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(SK_ColorBLUE);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLUE));
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, false);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(false));
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a color and style over the text end and check the resulting breaks.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (INT_MAX should be used instead of the text length for the range end)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t text_length = render_text->text().length();
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, Range(0, text_length));
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, text_length));
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color_end;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color_end.push_back(std::pair<size_t, SkColor>(0, SK_ColorRED));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color_end));
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style_end;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(0, false));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(2, true));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style_end));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure ranged values adjust to accommodate text length changes.
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(0, 2));
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(3, 6));
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(7, text_length));
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_italic;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(0, true));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(2, false));
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(3, true));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(6, false));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(7, true));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Truncating the text should trim any corresponding breaks.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("0123456"));
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.resize(4);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("01234"));
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.resize(3);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Appending text should extend the terminal styles without changing breaks.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_LINUX)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, PangoAttributes) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply ranged BOLD/ITALIC styles and check the resulting Pango attributes.
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, 4));
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(1, 3));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int start;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int end;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool bold;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool italic;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } cases[] = {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 0, 1,       false, false },
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 1, 2,       false, true  },
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 2, 3,       true,  true  },
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 3, 4,       true,  false },
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 4, INT_MAX, false, false },
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int start = 0, end = 0;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderTextLinux* rt_linux = static_cast<RenderTextLinux*>(render_text.get());
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rt_linux->EnsureLayout();
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrList* attributes = pango_layout_get_attributes(rt_linux->layout_);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrIterator* iter = pango_attr_list_get_iterator(attributes);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_range(iter, &start, &end);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].start, start);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].end, end);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PangoFontDescription* font = pango_font_description_new();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_get_font(iter, font, NULL, NULL);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* description_string = pango_font_description_to_string(font);
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::string16 desc = ASCIIToUTF16(description_string);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool bold = desc.find(ASCIIToUTF16("Bold")) != std::string::npos;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].bold, bold);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool italic = desc.find(ASCIIToUTF16("Italic")) != std::string::npos;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].italic, italic);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_next(iter);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_font_description_free(font);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_free(description_string);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pango_attr_iterator_next(iter));
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pango_attr_iterator_destroy(iter);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVisualCursorMotionInObscuredField(RenderText* render_text,
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           const base::string16& text,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool select) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(render_text->obscured());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(text);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = text.length();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select);
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, select);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 1; j <= len; ++j) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, select);
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_BACKWARD),
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = len - 1; j >= 0; --j) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, select);
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_FORWARD),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, select);
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD),
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, select);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, ObscuredText) {
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 seuss = ASCIIToUTF16("hop on pop");
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 no_seuss = ASCIIToUTF16("**********");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetLayoutText() returns asterisks when the obscured bit is set.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(seuss);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(false);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->GetLayoutText());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Surrogate pairs are counted as one code point.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char16 invalid_surrogates[] = {0xDC00, 0xD800, 0};
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(invalid_surrogates);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**"), render_text->GetLayoutText());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char16 valid_surrogates[] = {0xD800, 0xDC00, 0};
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(valid_surrogates);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*"), render_text->GetLayoutText());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test index conversion and cursor validity with a valid surrogate pair.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->TextIndexToLayoutIndex(0U));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(1U));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(2U));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->LayoutIndexToTextIndex(0U));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->LayoutIndexToTextIndex(1U));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->IsCursorablePosition(0U));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(render_text->IsCursorablePosition(1U));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->IsCursorablePosition(2U));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindCursorPosition() should not return positions between a surrogate pair.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 20, 20));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(0, 0)).caret_pos(), 0U);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(20, 0)).caret_pos(), 2U);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int x = -1; x <= 20; ++x) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel selection = render_text->FindCursorPosition(Point(x, 0));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(selection.caret_pos() == 0U || selection.caret_pos() == 2U);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetGlyphBounds() should yield the entire string bounds for text index 0.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetStringSize().width(),
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            static_cast<int>(render_text->GetGlyphBounds(0U).length()));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cursoring is independent of underlying characters when text is obscured.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const texts[] = {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"hop on pop",                              // Check LTR word boundaries.
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"\x05d0\x05d1 \x05d0\x05d2 \x05d1\x05d2",  // Check RTL word boundaries.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(texts); ++i) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text = WideToUTF16(texts[i]);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, false);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, true);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(RenderTextTest, RevealObscuredText) {
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 seuss = ASCIIToUTF16("hop on pop");
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 no_seuss = ASCIIToUTF16("**********");
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(seuss);
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(true);
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Valid reveal index and new revealed index clears previous one.
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("h*********"), render_text->GetLayoutText());
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*o********"), render_text->GetLayoutText());
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**p*******"), render_text->GetLayoutText());
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Invalid reveal index.
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(-1);
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(seuss.length() + 1);
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // SetObscured clears the revealed index.
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("h*********"), render_text->GetLayoutText());
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(false);
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->GetLayoutText());
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(true);
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // SetText clears the revealed index.
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("new"));
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("***"), render_text->GetLayoutText());
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**w"), render_text->GetLayoutText());
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("new longer"));
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**********"), render_text->GetLayoutText());
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Text with invalid surrogates.
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 invalid_surrogates[] = {0xDC00, 0xD800, 'h', 'o', 'p', 0};
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(invalid_surrogates);
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*****"), render_text->GetLayoutText());
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 invalid_expect_0[] = {0xDC00, '*', '*', '*', '*', 0};
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(invalid_expect_0, render_text->GetLayoutText());
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 invalid_expect_1[] = {'*', 0xD800, '*', '*', '*', 0};
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(invalid_expect_1, render_text->GetLayoutText());
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**h**"), render_text->GetLayoutText());
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Text with valid surrogates before and after the reveal index.
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 valid_surrogates[] =
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      {0xD800, 0xDC00, 'h', 'o', 'p', 0xD800, 0xDC00, 0};
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(valid_surrogates);
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*****"), render_text->GetLayoutText());
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 valid_expect_0_and_1[] = {0xD800, 0xDC00, '*', '*', '*', '*', 0};
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText());
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText());
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*h***"), render_text->GetLayoutText());
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(5);
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const char16 valid_expect_5_and_6[] = {'*', '*', '*', '*', 0xD800, 0xDC00, 0};
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText());
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(6);
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText());
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedText) {
400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  struct {
401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const wchar_t* text;
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const wchar_t* layout_text;
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } cases[] = {
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Strings shorter than the truncation length should be laid out in full.
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"",        L""        },
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kWeak,      kWeak      },
407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtr,       kLtr       },
408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtrRtl,    kLtrRtl    },
409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtrRtlLtr, kLtrRtlLtr },
410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtl,       kRtl       },
411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtlLtr,    kRtlLtr    },
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtlLtrRtl, kRtlLtrRtl },
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Strings as long as the truncation length should be laid out in full.
414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01234",   L"01234"   },
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Long strings should be truncated with an ellipsis appended at the end.
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012345",                  L"0123\x2026"     },
417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L" . ",              L"012 \x2026"     },
418558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"abc",              L"012a\x2026"     },
419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"a" L"\x5d0\x5d1",  L"012a\x2026"     },
420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"a" L"\x5d1" L"b",  L"012a\x2026"     },
421558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0\x5d1\x5d2",  L"012\x5d0\x2026" },
422558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0\x5d1" L"a",  L"012\x5d0\x2026" },
423558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0" L"a" L"\x5d1",    L"012\x5d0\x2026" },
424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Surrogate pairs should be truncated reasonably enough.
425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0123\x0915\x093f",              L"0123\x2026"                },
426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0\x05e9\x05bc\x05c1\x05b8",     L"0\x05e9\x05bc\x05c1\x05b8" },
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01\x05e9\x05bc\x05c1\x05b8",    L"01\x05e9\x05bc\x2026"      },
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012\x05e9\x05bc\x05c1\x05b8",   L"012\x05e9\x2026"           },
429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0123\x05e9\x05bc\x05c1\x05b8",  L"0123\x2026"                },
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01234\x05e9\x05bc\x05c1\x05b8", L"0123\x2026"                },
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012\xF0\x9D\x84\x9E",           L"012\xF0\x2026"             },
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(5);
436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    render_text->SetText(WideToUTF16(cases[i].text));
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(WideToUTF16(cases[i].text), render_text->text());
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(WideToUTF16(cases[i].layout_text), render_text->GetLayoutText())
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        << "For case " << i << ": " << cases[i].text;
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedObscuredText) {
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(3);
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetObscured(true);
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"abcdef"));
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(WideToUTF16(L"abcdef"), render_text->text());
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(WideToUTF16(L"**\x2026"), render_text->GetLayoutText());
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedCursorMovementLTR) {
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(2);
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"abcd"));
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model());
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SelectionModel> expected;
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
467558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The cursor hops over the ellipsis and elided text to the line end.
468558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.clear();
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The cursor hops over the elided text to preceeding text.
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedCursorMovementRTL) {
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(2);
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3"));
485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model());
489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SelectionModel> expected;
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
495558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The cursor hops over the ellipsis and elided text to the line end.
496558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.clear();
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The cursor hops over the elided text to preceeding text.
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetTextDirection) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* text;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection text_direction;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Blank strings and those with no/weak directionality default to LTR.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { L"",        base::i18n::LEFT_TO_RIGHT },
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kWeak,      base::i18n::LEFT_TO_RIGHT },
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong LTR characters.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtr,       base::i18n::LEFT_TO_RIGHT },
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtl,    base::i18n::LEFT_TO_RIGHT },
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtlLtr, base::i18n::LEFT_TO_RIGHT },
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong RTL characters.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtl,       base::i18n::RIGHT_TO_LEFT },
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtr,    base::i18n::RIGHT_TO_LEFT },
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtrRtl, base::i18n::RIGHT_TO_LEFT },
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Toggle the application default text direction (to try each direction).
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection ui_direction = base::i18n::IsRTL() ?
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that directionality modes yield the correct text directions.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j].text));
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), cases[j].text_direction);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), ui_direction);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_RTL);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kLtr));
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kRtl));
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure LTR.
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abc"));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |expected| saves the expected SelectionModel when moving cursor from left
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to right.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtl) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last one is the expected END position.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtlLtr) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL-LTR.
615558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"a" L"\x05d1" L"b"));
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtl) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure RTL.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtr) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR
660558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2" L"abc"));
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtrRtl) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR-RTL.
688558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05d0" L"a" L"\x05d1"));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): temporarily disable in platform Win since the complex script
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// characters turned into empty square due to font regression. So, not able
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test 2 characters belong to the same grapheme.
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) {
7377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Meiryo UI uses single-glyph ligatures for 'ff' and 'ffi', but each letter
7397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // (code point) has unique bounds, so mid-glyph cursoring should be possible.
7407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  render_text->SetFont(Font("Meiryo UI", 12));
7417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"ff ffi"));
7427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
7437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (size_t i = 0; i < render_text->text().length(); ++i) {
7447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
7457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(i + 1, render_text->cursor_position());
7467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
7477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
7487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
7497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GraphemePositions) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR abc, LTR 2-character grapheme.
752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kText1 =
753558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0915\x093f" L"abc" L"\x0915\x093f");
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, LTR 2-character grapheme, LTR cd.
756558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::string16 kText2 = WideToUTF16(L"ab" L"\x0915\x093f" L"cd");
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // two characters forming the surrogate pair 0x0001D11E.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSurrogate = "\xF0\x9D\x84\x9E";
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, UTF16 surrogate pair, LTR cd.
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kText3 = UTF8ToUTF16("ab" + kSurrogate + "cd");
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t index;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_previous;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_next;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 0, 0, 0 },
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 1, 0, 0 },
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 50, 0, 0 },
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 0, 0, 2 },
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 1, 0, 2 },
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 2, 0, 3 },
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 3, 2, 4 },
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 4, 3, 5 },
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 5, 4, 7 },
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 6, 5, 7 },
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 7, 5, 7 },
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 8, 7, 7 },
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 50, 7, 7 },
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 0, 0, 1 },
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 1, 0, 2 },
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 2, 1, 4 },
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 3, 2, 4 },
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 4, 2, 5 },
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 5, 4, 6 },
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 6, 5, 6 },
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 7, 6, 6 },
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 50, 6, 6 },
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 0, 0, 1 },
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 1, 0, 2 },
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 2, 1, 4 },
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 3, 2, 4 },
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 4, 2, 5 },
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 5, 4, 6 },
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 6, 5, 6 },
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 7, 6, 6 },
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 50, 6, 6 },
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                  font support for some scripts - http://crbug.com/106450
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t next = render_text->IndexOfAdjacentGrapheme(cases[i].index,
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       CURSOR_FORWARD);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_next, next);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(render_text->IsCursorablePosition(next));
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t previous = render_text->IndexOfAdjacentGrapheme(cases[i].index,
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           CURSOR_BACKWARD);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_previous, previous);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(render_text->IsCursorablePosition(previous));
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, EdgeSelectionModels) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simple Latin text.
829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kLatin = WideToUTF16(L"abc");
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme.
831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f");
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR a, LTR 2-character grapheme.
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kHindiLatin =
834558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0915\x093f" L"a" L"\x0915\x093f");
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme.
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kRTLGrapheme = WideToUTF16(L"\x05e0\x05b8");
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme, LTR a, RTL 2-character grapheme.
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kHebrewLatin =
839558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x05e0\x05b8" L"a" L"\x05e0\x05b8");
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::i18n::TextDirection expected_text_direction;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), base::i18n::LEFT_TO_RIGHT },
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLatin,       base::i18n::LEFT_TO_RIGHT },
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLTRGrapheme, base::i18n::LEFT_TO_RIGHT },
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHindiLatin,  base::i18n::LEFT_TO_RIGHT },
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRTLGrapheme, base::i18n::RIGHT_TO_LEFT },
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHebrewLatin, base::i18n::RIGHT_TO_LEFT },
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                  font support for some scripts - http://crbug.com/106450
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ltr = (cases[i].expected_text_direction == base::i18n::LEFT_TO_RIGHT);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start_edge =
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_LEFT : CURSOR_RIGHT);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(start_edge, SelectionModel(0, CURSOR_BACKWARD));
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end_edge =
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_RIGHT : CURSOR_LEFT);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end_edge, SelectionModel(cases[i].text.length(), CURSOR_FORWARD));
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SelectAll) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const cases[] =
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl };
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that SelectAll respects the |reversed| argument regardless of
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // application locale and text content directionality.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
882d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SelectionModel expected_reversed(Range(3, 0), CURSOR_FORWARD);
883d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SelectionModel expected_forwards(Range(0, 3), CURSOR_BACKWARD);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test that an empty string produces an empty selection model.
889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    render_text->SetText(base::string16());
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(render_text->selection_model(), SelectionModel());
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the weak, LTR, RTL, and Bidi string cases.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j]));
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(false);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_forwards);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(true);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_reversed);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Left arrow on select ranging (6, 4).
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
910d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
912d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
914d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(5), render_text->selection());
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
916d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
918d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6, 5), render_text->selection());
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
920d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6, 4), render_text->selection());
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
922d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Right arrow on select ranging (4, 6).
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
926d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(0), render_text->selection());
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
928d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(1), render_text->selection());
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
930d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(2), render_text->selection());
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
932d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(3), render_text->selection());
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
934d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(5), render_text->selection());
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
938d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4, 5), render_text->selection());
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4, 6), render_text->selection());
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): Make these work on Windows.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MoveLeftRightByWordVerifier(RenderText* render_text,
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const wchar_t* str) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(str));
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from left ro right.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first_word = true;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, test moving by word from a word break position, such as from
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "|abc def" to "abc| def".
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For testing simplicity, each word is a 3-character word.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then, test moving by word from positions inside the word, such as from
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "a|bc def" to "abc| def", and from "ab|c def" to "abc| def".
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from right to left.
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_word = true;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText) {
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For testing simplicity, each word is a 3-character word.
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const wchar_t*> test;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc");
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def");
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3");
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3");
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3 hij");
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 hij opq");
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
1027558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                 L" \x05E7\x05E8\x05E9" L" opq rst uvw");
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 abc");
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 abc def");
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 \x05E7\x05E8\x05E9"
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij");
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 abc \x05E1\x05E2\x05E3");
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 abc def"
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 \x05D7\x05D8\x05D9"
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test.size(); ++i)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MoveLeftRightByWordVerifier(render_text.get(), test[i]);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"ab\x05E1"));
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "abC|" to the left should return "|abC".
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "ab|C".
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|abC" to the right returns "abC|".
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05E1\x05E2" L"a"));
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For logical text "BCa", moving the cursor by word from "aCB|" to the left
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns "|aCB".
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|aCB" to the right should return "aCB|".
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "a|CB".
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc     def"));
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(11U, render_text->cursor_position());
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x6211\x4EEC\x53BB\x516C\x56ED\x73A9"));
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, render_text->cursor_position());
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1108558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#if defined(OS_WIN)
1109558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(RenderTextTest, Win_LogicalClusters) {
1110558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<RenderTextWin> render_text(
1111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      static_cast<RenderTextWin*>(RenderText::CreateInstance()));
1112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::string16 test_string =
1114558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0930\x0930\x0930\x0930\x0930");
1115558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(test_string);
1116558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->EnsureLayout();
1117558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_EQ(1U, render_text->runs_.size());
1118558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  WORD* logical_clusters = render_text->runs_[0]->logical_clusters.get();
1119558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (size_t i = 0; i < test_string.length(); ++i)
1120558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    EXPECT_EQ(i, logical_clusters[i]);
1121558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
1122558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif  // defined(OS_WIN)
1123558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeSanity) {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Size string_size = render_text->GetStringSize();
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.width(), 0);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.height(), 0);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): This test fails because PlatformFontMac uses point font
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  sizes instead of pixel sizes like other implementations.
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeEmptyString) {
1136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Ascent and descent of Arial and Symbol are different on most platforms.
1137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FontList font_list("Arial,Symbol, 16px");
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(font_list);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The empty string respects FontList metrics for non-zero height
1142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and baseline.
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(base::string16());
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetStringSize().width());
1146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16(" "));
1149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
1150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
1155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Check that Arial and Symbol have different font metrics.
1156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font arial_font("Arial", 16);
1157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font symbol_font("Symbol", 16);
1158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_NE(arial_font.GetHeight(), symbol_font.GetHeight());
1159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_NE(arial_font.GetBaseline(), symbol_font.GetBaseline());
1160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // "a" should be rendered with Arial, not with Symbol.
1161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* arial_font_text = "a";
1162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // "®" (registered trademark symbol) should be rendered with Symbol,
1163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // not with Arial.
1164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* symbol_font_text = "\xC2\xAE";
1165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font smaller_font = arial_font;
1167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font larger_font = symbol_font;
1168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* smaller_font_text = arial_font_text;
1169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* larger_font_text = symbol_font_text;
1170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (symbol_font.GetHeight() < arial_font.GetHeight() &&
1171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      symbol_font.GetBaseline() < arial_font.GetBaseline()) {
1172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::swap(smaller_font, larger_font);
1173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::swap(smaller_font_text, larger_font_text);
1174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_LT(smaller_font.GetHeight(), larger_font.GetHeight());
1176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_LT(smaller_font.GetBaseline(), larger_font.GetBaseline());
1177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Check |smaller_font_text| is rendered with the smaller font.
1179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16(smaller_font_text));
1181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFont(smaller_font);
1182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(smaller_font.GetHeight(), render_text->GetStringSize().height());
1183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(smaller_font.GetBaseline(), render_text->GetBaseline());
1184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Layout the same text with mixed fonts.  The text should be rendered with
1186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the smaller font, but the height and baseline are determined with the
1187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // metrics of the font list, which is equal to the larger font.
1188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Font> fonts;
1189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fonts.push_back(smaller_font);  // The primary font is the smaller font.
1190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fonts.push_back(larger_font);
1191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FontList font_list(fonts);
1192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(font_list);
1193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_LT(smaller_font.GetHeight(), render_text->GetStringSize().height());
1194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_LT(smaller_font.GetBaseline(), render_text->GetBaseline());
1195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
1196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
1197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SetFont) {
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFont(Font("Arial", 12));
1202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ("Arial", render_text->GetPrimaryFont().GetFontName());
1203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(12, render_text->GetPrimaryFont().GetFontSize());
1204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(RenderTextTest, SetFontList) {
1207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(FontList("Arial,Symbol, 13px"));
1209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const std::vector<Font>& fonts = render_text->font_list().GetFonts();
1210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(2U, fonts.size());
1211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ("Arial", fonts[0].GetFontName());
1212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ("Symbol", fonts[1].GetFontName());
1213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(13, render_text->GetPrimaryFont().GetFontSize());
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeBoldWidth) {
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_width = render_text->GetStringSize().width();
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_width, 0);
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply a bold style and check that the new width is greater.
12247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  render_text->SetStyle(BOLD, true);
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bold_width = render_text->GetStringSize().width();
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(bold_width, plain_width);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, apply a plain style over the first word only.
1229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, false, Range(0, 5));
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_bold_width = render_text->GetStringSize().width();
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_bold_width, plain_width);
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(plain_bold_width, bold_width);
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeHeight) {
1236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::string16 cases[] = {
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"Hello World!"),  // English
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x6328\x62f6"),  // Japanese
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x0915\x093f"),  // Hindi
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x05e0\x05b8"),  // Hebrew
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font default_font;
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font larger_font = default_font.DeriveFont(24, default_font.GetStyle());
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(larger_font.GetHeight(), default_font.GetHeight());
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetFont(default_font);
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(cases[i]);
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height1 = render_text->GetStringSize().height();
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height1, 0);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that setting the larger font increases the height.
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetFont(larger_font);
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height2 = render_text->GetStringSize().height();
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height2, height1);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetBaselineSanity) {
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int baseline = render_text->GetBaseline();
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(baseline, 0);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, CursorBoundsInReplacementMode) {
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(100, 17));
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_b(1, CURSOR_FORWARD);
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_c(2, CURSOR_FORWARD);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_around_b = render_text->GetCursorBounds(sel_b, false);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_b = render_text->GetCursorBounds(sel_b, true);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_c = render_text->GetCursorBounds(sel_c, true);
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.x(), cursor_before_b.x());
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.right(), cursor_before_c.x());
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffset) {
128390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The default horizontal text offset differs for LTR and RTL, and is only set
128490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // when the RenderText object is created.  This test will check the default in
128590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // LTR mode, and the next test will check the RTL default.
128690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
128790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(false);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set display area's size equal to the font size.
12937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const Size font_size(render_text->GetContentWidth(),
12947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       render_text->GetStringSize().height());
129590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Vector2d offset = render_text->GetLineOffset(0);
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(offset.IsZero());
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set display area's size greater than font size.
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kEnlargement = 2;
130390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  display_rect.Inset(0, 0, -kEnlargement, -kEnlargement);
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check the default horizontal and vertical alignment.
1307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
130890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.y());
130990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
131090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
131190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check explicitly setting the horizontal alignment.
131290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_LEFT);
1313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
131490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
131590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_CENTER);
1316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
131790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.x());
131890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_RIGHT);
1319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
132090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.x());
132190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
132290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check explicitly setting the vertical alignment.
132390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_TOP);
1324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
132590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.y());
132690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_VCENTER);
1327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
132890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement / 2, offset.y());
132990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetVerticalAlignment(ALIGN_BOTTOM);
1330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
133190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.y());
133290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
133390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
133490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
133590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
133690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) {
133790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This only checks the default horizontal alignment in RTL mode; all other
1338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // GetLineOffset(0) attributes are checked by the test above.
133990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
134090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(true);
134190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
134290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
134390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
134490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kEnlargement = 2;
13457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const Size font_size(render_text->GetContentWidth() + kEnlargement,
13467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       render_text->GetStringSize().height());
134790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
134890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
1349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Vector2d offset = render_text->GetLineOffset(0);
135090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.x());
135190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SameFontForParentheses) {
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char16 left_char;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char16 right_char;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } punctuation_pairs[] = {
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '(', ')' },
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '{', '}' },
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '<', '>' },
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)") },
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)English
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)Hello World") },
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)") },
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)Japanese
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)\x6328\x62f6") },
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Japanese)English
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x6328\x62f6)Hello World") },
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)") },
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)Hindi
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)\x0915\x093f") },
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hindi)English
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x0915\x093f)Hello World") },
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)") },
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)Hebrew
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)\x05e0\x05b8") },
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hebrew)English
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x05e0\x05b8)Hello World") },
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text = cases[i].text;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t start_paren_char_index = text.find('(');
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_NE(base::string16::npos, start_paren_char_index);
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t end_paren_char_index = text.find(')');
1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_NE(base::string16::npos, end_paren_char_index);
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(punctuation_pairs); ++j) {
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[start_paren_char_index] = punctuation_pairs[j].left_char;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[end_paren_char_index] = punctuation_pairs[j].right_char;
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(text);
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<RenderText::FontSpan> spans =
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          render_text->GetFontSpansForTesting();
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int start_paren_span_index = -1;
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int end_paren_span_index = -1;
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t k = 0; k < spans.size(); ++k) {
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, start_paren_char_index))
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start_paren_span_index = k;
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, end_paren_char_index))
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          end_paren_span_index = k;
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, start_paren_span_index);
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, end_paren_span_index);
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& start_font = spans[start_paren_span_index].first;
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& end_font = spans[end_paren_span_index].first;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontName(), end_font.GetFontName());
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontSize(), end_font.GetFontSize());
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetStyle(), end_font.GetStyle());
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure the caret width is always >=1 so that the correct
14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// caret is drawn at high DPI. crbug.com/164100.
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, CaretWidth) {
14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_GE(render_text->GetUpdatedCursorBounds().width(), 1);
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(RenderTextTest, SelectWord) {
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16(" foo  a.bc.d bar"));
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  struct {
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t cursor;
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t selection_start;
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t selection_end;
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  } cases[] = {
1446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 0,   0,  1 },
1447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 1,   1,  4 },
1448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 2,   1,  4 },
1449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 3,   1,  4 },
1450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 4,   4,  6 },
1451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 5,   4,  6 },
1452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 6,   6,  7 },
1453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 7,   7,  8 },
1454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 8,   8, 10 },
1455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 9,   8, 10 },
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 10, 10, 11 },
1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 11, 11, 12 },
1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 12, 12, 13 },
1459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 13, 13, 16 },
1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 14, 13, 16 },
1461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 15, 13, 16 },
1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 16, 13, 16 },
1463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
1464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SetCursorPosition(cases[i].cursor);
1467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SelectWord();
1468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(Range(cases[i].selection_start, cases[i].selection_end),
1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              render_text->selection());
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Make sure the last word is selected when the cursor is at text.length().
1474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(RenderTextTest, LastWordSelected) {
1475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL1 = "http://www.google.com";
1476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL2 = "http://www.google.com/something/";
1477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL1));
1481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL1.length());
1482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1483a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("com"), GetSelectedText(render_text.get()));
1484a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL2));
1487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL2.length());
1488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("/"), GetSelectedText(render_text.get()));
1490a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1491a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
1492a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1493a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// When given a non-empty selection, SelectWord should expand the selection to
1494a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// nearest word boundaries.
1495a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)TEST_F(RenderTextTest, SelectMultipleWords) {
1496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string kTestURL = "http://www.google.com";
1497a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1498a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1499a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1500a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL));
1501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SelectRange(Range(16, 20));
1502a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1503a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1504a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1505a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1506a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // SelectWord should preserve the selection direction.
1507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SelectRange(Range(20, 16));
1508a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1509a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1510a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(render_text->selection().is_reversed());
1511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorLTR) {
15172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::IsRTL());
15182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::ICUIsRTL());
15192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
1533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
15342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
1538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
1539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
15592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
1564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) {
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the application default text direction to RTL.
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(true);
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the application default text direction to LTR.
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(was_rtl);
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Changing colors between or inside ligated glyphs should not break shaping.
1633558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(RenderTextTest, SelectionKeepsLigatures) {
1634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const wchar_t* kTestStrings[] = {
1635a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    L"\x644\x623",
1636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    L"\x633\x627"
1637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
1638558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1639558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1640558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->set_selection_color(SK_ColorRED);
1641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Canvas canvas;
1642a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1643a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
1645a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const int expected_width = render_text->GetStringSize().width();
1646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD));
1647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    EXPECT_EQ(expected_width, render_text->GetStringSize().width());
1648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Draw the text. It shouldn't hit any DCHECKs or crash.
1649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // See http://crbug.com/214150
1650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->Draw(&canvas);
1651a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
1652a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1653558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
1654558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
165558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_WIN)
1656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings wrap onto multiple lines for a small available width.
1657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_MinWidth) {
1658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl,
1659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                    kRtlLtr, kRtlLtrRtl };
1660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
1662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateInstance()));
1663d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(1, 1000));
1664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
1669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
1670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
1671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_GT(render_text->lines_.size(), 1U);
1672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings wrap onto multiple lines for a normal available width.
1676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_NormalWidth) {
1677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(ckocagil): Enable this test on XP.
1678d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_WIN)
1679d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
1680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
1681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
1682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1683d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const struct {
1684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const wchar_t* const text;
1685d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Range first_line_char_range;
1686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Range second_line_char_range;
1687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } kTestStrings[] = {
1688d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { L"abc defg hijkl", Range(0, 9), Range(9, 14) },
1689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { L"qwertyuiop", Range(0, 8), Range(8, 10) },
1690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD",
1691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          Range(4, 10), Range(0, 4) }
1692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
1693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1694d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
1695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateInstance()));
1696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(50, 1000));
1697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1699d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) {
1701d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
1702d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i].text));
1703d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
1704d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(2U, render_text->lines_.size());
1705d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(1U, render_text->lines_[0].segments.size());
1706d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kTestStrings[i].first_line_char_range,
1707d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              render_text->lines_[0].segments[0].char_range);
1708d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(1U, render_text->lines_[1].segments.size());
1709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kTestStrings[i].second_line_char_range,
1710d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              render_text->lines_[1].segments[0].char_range);
1711d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings don't wrap onto multiple lines for a sufficient available
1715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// width.
1716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_SufficientWidth) {
1717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c",
1718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                    L"\x62E\x628\x632", L"\x62E \x628 \x632" };
1719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1720d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
1721d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateInstance()));
1722d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(30, 1000));
1723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1724d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1725d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
1728d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
1729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
1730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(1U, render_text->lines_.size());
1731d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1732d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1733d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif  // defined(OS_WIN)
1734d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1735d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_WIN)
173658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TEST_F(RenderTextTest, Win_BreakRunsByUnicodeBlocks) {
173758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
173858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateInstance()));
173958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
174058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  render_text->SetText(WideToUTF16(L"x\x25B6y"));
174158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  render_text->EnsureLayout();
174258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_EQ(3U, render_text->runs_.size());
174358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(0, 1), render_text->runs_[0]->range);
174458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(1, 2), render_text->runs_[1]->range);
174558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text->runs_[2]->range);
174658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
174758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  render_text->SetText(WideToUTF16(L"x \x25B6 y"));
174858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  render_text->EnsureLayout();
174958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_EQ(3U, render_text->runs_.size());
175058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(0, 2), render_text->runs_[0]->range);
175158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text->runs_[1]->range);
175258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_EQ(Range(3, 5), render_text->runs_[2]->range);
175358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
175458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
175558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif  // !defined(OS_WIN)
175658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
1758