render_text_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/i18n/break_iterator.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_util.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/break_list.h"
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/gfx/canvas.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gfx/render_text_harfbuzz.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
22558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/gfx/render_text_win.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_LINUX) && !defined(USE_OZONE)
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/gfx/render_text_pango.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UTF8ToUTF16;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::WideToUTF16;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various weak, LTR, RTL, and Bidi string cases with three characters each.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kWeak[] =      L" . ";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kLtr[] =       L"abc";
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const wchar_t kRtl[] =       L"\x5d0\x5d1\x5d2";
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if !defined(OS_MACOSX)
42bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kLtrRtl[] =    L"a" L"\x5d0\x5d1";
43bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kLtrRtlLtr[] = L"a" L"\x5d1" L"b";
44bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kRtlLtr[] =    L"\x5d0\x5d1" L"a";
45bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1";
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks whether |range| contains |index|. This is not the same as calling
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// range.Contains(Range(index)), which returns true if |index| == |range.end()|.
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool IndexInRange(const Range& range, size_t index) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return index >= range.start() && index < range.end();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::string16 GetSelectedText(RenderText* render_text) {
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return render_text->text().substr(render_text->selection().GetMin(),
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                    render_text->selection().length());
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A test utility function to set the application default text direction.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetRTL(bool rtl) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override the current locale/direction.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(rtl, base::i18n::IsRTL());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if !defined(OS_MACOSX)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Ensure cursor movement in the specified |direction| yields |expected| values.
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RunMoveCursorLeftRightTest(RenderText* render_text,
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                const std::vector<SelectionModel>& expected,
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                VisualCursorDirection direction) {
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < expected.size(); ++i) {
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SCOPED_TRACE(base::StringPrintf("Going %s; expected value index %d.",
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        direction == CURSOR_LEFT ? "left" : "right", static_cast<int>(i)));
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(expected[i], render_text->selection_model());
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    render_text->MoveCursor(CHARACTER_BREAK, direction, false);
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that cursoring is clamped at the line edge.
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected.back(), render_text->selection_model());
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that it is the line edge.
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, direction, false);
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected.back(), render_text->selection_model());
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // !defined(OS_MACOSX)
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RenderTextTest : public testing::Test {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DefaultStyle) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the default styles applied to new instances and adjusted text.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(render_text->text().empty());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLACK));
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t style = 0; style < NUM_TEXT_STYLES; ++style)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[style].EqualsValueForTesting(false));
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, SetColorAndStyle) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure custom default styles persist across setting and clearing text.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkColor color = SK_ColorRED;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(color);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, true);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(UNDERLINE, false);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const wchar_t* const cases[] = { kWeak, kLtr, L"Hello", kRtl, L"", L"" };
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->colors().EqualsValueForTesting(color));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(true));
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsValueForTesting(false));
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(WideToUTF16(cases[i]));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ensure custom default styles can be applied after text has been set.
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i == 1)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_text->SetStyle(STRIKE, true);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i >= 1)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_TRUE(render_text->styles()[STRIKE].EqualsValueForTesting(true));
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, ApplyColorAndStyle) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a ranged color and style and check the resulting breaks.
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, Range(1, 4));
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, 5));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(0, SK_ColorBLACK));
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(1, SK_ColorRED));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color.push_back(std::pair<size_t, SkColor>(4, SK_ColorBLACK));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color));
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(0, false));
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(2, true));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style.push_back(std::pair<size_t, bool>(5, false));
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure setting a color and style overrides the ranged colors and styles.
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetColor(SK_ColorBLUE);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsValueForTesting(SK_ColorBLUE));
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetStyle(BOLD, false);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsValueForTesting(false));
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply a color and style over the text end and check the resulting breaks.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (INT_MAX should be used instead of the text length for the range end)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t text_length = render_text->text().length();
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyColor(SK_ColorRED, Range(0, text_length));
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, text_length));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, SkColor> > expected_color_end;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_color_end.push_back(std::pair<size_t, SkColor>(0, SK_ColorRED));
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->colors().EqualsForTesting(expected_color_end));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_style_end;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(0, false));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_style_end.push_back(std::pair<size_t, bool>(2, true));
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[BOLD].EqualsForTesting(expected_style_end));
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure ranged values adjust to accommodate text length changes.
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(0, 2));
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(3, 6));
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(7, text_length));
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::pair<size_t, bool> > expected_italic;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(0, true));
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(2, false));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(3, true));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(6, false));
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_italic.push_back(std::pair<size_t, bool>(7, true));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Changing the text should clear any breaks except for the first one.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("0123456"));
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  expected_italic.resize(1);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->ApplyStyle(ITALIC, false, Range(2, 4));
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->SetText(ASCIIToUTF16("012345678"));
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->ApplyStyle(ITALIC, false, Range(0, 1));
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->SetText(ASCIIToUTF16("0123456"));
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  expected_italic.begin()->second = false;
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->ApplyStyle(ITALIC, true, Range(2, 4));
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(tmoniuszko): Enable when RenderTextMac::IsValidCursorIndex is
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //                   implemented.
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(OS_MACOSX)
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Styles shouldn't be changed mid-grapheme.
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->SetText(WideToUTF16(
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      L"0" L"\x0915\x093f" L"1" L"\x0915\x093f" L"2"));
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_text->ApplyStyle(UNDERLINE, true, Range(2, 5));
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<std::pair<size_t, bool> > expected_underline;
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  expected_underline.push_back(std::pair<size_t, bool>(0, false));
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  expected_underline.push_back(std::pair<size_t, bool>(1, true));
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  expected_underline.push_back(std::pair<size_t, bool>(6, false));
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(render_text->styles()[UNDERLINE].EqualsForTesting(
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      expected_underline));
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // OS_MACOSX
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_LINUX) && !defined(USE_OZONE)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, PangoAttributes) {
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateNativeInstance());
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("012345678"));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Apply ranged BOLD/ITALIC styles and check the resulting Pango attributes.
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, true, Range(2, 4));
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(ITALIC, true, Range(1, 3));
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int start;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int end;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool bold;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool italic;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } cases[] = {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 0, 1,       false, false },
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 1, 2,       false, true  },
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 2, 3,       true,  true  },
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 3, 4,       true,  false },
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { 4, INT_MAX, false, false },
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int start = 0, end = 0;
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RenderTextPango* rt_linux = static_cast<RenderTextPango*>(render_text.get());
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rt_linux->EnsureLayout();
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrList* attributes = pango_layout_get_attributes(rt_linux->layout_);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PangoAttrIterator* iter = pango_attr_list_get_iterator(attributes);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_range(iter, &start, &end);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].start, start);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].end, end);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PangoFontDescription* font = pango_font_description_new();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_get_font(iter, font, NULL, NULL);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* description_string = pango_font_description_to_string(font);
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::string16 desc = ASCIIToUTF16(description_string);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool bold = desc.find(ASCIIToUTF16("Bold")) != std::string::npos;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].bold, bold);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const bool italic = desc.find(ASCIIToUTF16("Italic")) != std::string::npos;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(cases[i].italic, italic);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_attr_iterator_next(iter);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pango_font_description_free(font);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_free(description_string);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(pango_attr_iterator_next(iter));
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pango_attr_iterator_destroy(iter);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVisualCursorMotionInObscuredField(RenderText* render_text,
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                           const base::string16& text,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool select) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(render_text->obscured());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(text);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = text.length();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, select);
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD),
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, select);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 1; j <= len; ++j) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, select);
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_BACKWARD),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = len - 1; j >= 0; --j) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, select);
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(SelectionModel(Range(select ? 0 : j, j), CURSOR_FORWARD),
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              render_text->selection_model());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, select);
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(SelectionModel(Range(select ? 0 : len, len), CURSOR_FORWARD),
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->selection_model());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, select);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, ObscuredText) {
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 seuss = ASCIIToUTF16("hop on pop");
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 no_seuss = ASCIIToUTF16("**********");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetLayoutText() returns asterisks when the obscured bit is set.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(seuss);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(false);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->GetLayoutText());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetObscured(true);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Surrogate pairs are counted as one code point.
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 invalid_surrogates[] = {0xDC00, 0xD800, 0};
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(invalid_surrogates);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**"), render_text->GetLayoutText());
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 valid_surrogates[] = {0xD800, 0xDC00, 0};
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(valid_surrogates);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*"), render_text->GetLayoutText());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test index conversion and cursor validity with a valid surrogate pair.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->TextIndexToLayoutIndex(0U));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(1U));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, render_text->TextIndexToLayoutIndex(2U));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->LayoutIndexToTextIndex(0U));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->LayoutIndexToTextIndex(1U));
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_TRUE(render_text->IsValidCursorIndex(0U));
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_FALSE(render_text->IsValidCursorIndex(1U));
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EXPECT_TRUE(render_text->IsValidCursorIndex(2U));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FindCursorPosition() should not return positions between a surrogate pair.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 20, 20));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(0, 0)).caret_pos(), 0U);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->FindCursorPosition(Point(20, 0)).caret_pos(), 2U);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int x = -1; x <= 20; ++x) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel selection = render_text->FindCursorPosition(Point(x, 0));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(selection.caret_pos() == 0U || selection.caret_pos() == 2U);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetGlyphBounds() should yield the entire string bounds for text index 0.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetStringSize().width(),
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            static_cast<int>(render_text->GetGlyphBounds(0U).length()));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cursoring is independent of underlying characters when text is obscured.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const texts[] = {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl,
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"hop on pop",                              // Check LTR word boundaries.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    L"\x05d0\x05d1 \x05d0\x05d2 \x05d1\x05d2",  // Check RTL word boundaries.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(texts); ++i) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text = WideToUTF16(texts[i]);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, false);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestVisualCursorMotionInObscuredField(render_text.get(), text, true);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(RenderTextTest, RevealObscuredText) {
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 seuss = ASCIIToUTF16("hop on pop");
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 no_seuss = ASCIIToUTF16("**********");
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(seuss);
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(true);
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->text());
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Valid reveal index and new revealed index clears previous one.
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("h*********"), render_text->GetLayoutText());
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*o********"), render_text->GetLayoutText());
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**p*******"), render_text->GetLayoutText());
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Invalid reveal index.
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(-1);
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(seuss.length() + 1);
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // SetObscured clears the revealed index.
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("h*********"), render_text->GetLayoutText());
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(false);
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(seuss, render_text->GetLayoutText());
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetObscured(true);
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(no_seuss, render_text->GetLayoutText());
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // SetText clears the revealed index.
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("new"));
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("***"), render_text->GetLayoutText());
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**w"), render_text->GetLayoutText());
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("new longer"));
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**********"), render_text->GetLayoutText());
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Text with invalid surrogates.
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 invalid_surrogates[] = {0xDC00, 0xD800, 'h', 'o', 'p', 0};
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(invalid_surrogates);
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*****"), render_text->GetLayoutText());
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 invalid_expect_0[] = {0xDC00, '*', '*', '*', '*', 0};
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(invalid_expect_0, render_text->GetLayoutText());
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 invalid_expect_1[] = {'*', 0xD800, '*', '*', '*', 0};
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(invalid_expect_1, render_text->GetLayoutText());
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("**h**"), render_text->GetLayoutText());
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Text with valid surrogates before and after the reveal index.
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 valid_surrogates[] =
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      {0xD800, 0xDC00, 'h', 'o', 'p', 0xD800, 0xDC00, 0};
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(valid_surrogates);
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*****"), render_text->GetLayoutText());
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(0);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 valid_expect_0_and_1[] =
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      {0xD800, 0xDC00, '*', '*', '*', '*', 0};
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText());
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(1);
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_0_and_1, render_text->GetLayoutText());
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(2);
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("*h***"), render_text->GetLayoutText());
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(5);
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::char16 valid_expect_5_and_6[] =
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      {'*', '*', '*', '*', 0xD800, 0xDC00, 0};
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText());
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->RenderText::SetObscuredRevealIndex(6);
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(valid_expect_5_and_6, render_text->GetLayoutText());
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(RenderTextTest, ElidedText) {
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(skanuj) : Add more test cases for following
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - RenderText styles.
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - Cross interaction of truncate, elide and obscure.
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // - ElideText tests from text_elider.cc.
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct {
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const wchar_t* text;
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const wchar_t* layout_text;
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bool elision_expected;
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } cases[] = {
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Strings shorter than the elision width should be laid out in full.
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"",        L""       , false },
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { L"M",       L""       , false },
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { L" . ",     L" . "    , false },
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kWeak,      kWeak     , false },
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kLtr,       kLtr      , false },
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kLtrRtl,    kLtrRtl   , false },
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kLtrRtlLtr, kLtrRtlLtr, false },
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kRtl,       kRtl      , false },
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kRtlLtr,    kRtlLtr   , false },
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { kRtlLtrRtl, kRtlLtrRtl, false },
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Strings as long as the elision width should be laid out in full.
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"012ab",   L"012ab"  , false },
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Long strings should be elided with an ellipsis appended at the end.
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"012abc",              L"012a\x2026", true },
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"012ab" L"\x5d0\x5d1", L"012a\x2026", true },
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"012a" L"\x5d1" L"b",  L"012a\x2026", true },
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // No RLM marker added as digits (012) have weak directionality.
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"01" L"\x5d0\x5d1\x5d2", L"01\x5d0\x5d1\x2026", true },
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // RLM marker added as "ab" have strong LTR directionality.
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"ab" L"\x5d0\x5d1\x5d2", L"ab\x5d0\x5d1\x2026\x200f", true },
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Complex script is not handled. In this example, the "\x0915\x093f" is a
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // compound glyph, but only half of it is elided.
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"0123\x0915\x093f", L"0123\x0915\x2026", true },
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Surrogate pairs should be elided reasonably enough.
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"0\x05e9\x05bc\x05c1\x05b8",   L"0\x05e9\x05bc\x05c1\x05b8", false },
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"0\x05e9\x05bc\x05c1\x05b8",   L"0\x05e9\x05bc\x2026"      , true  },
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"01\x05e9\x05bc\x05c1\x05b8",  L"01\x05e9\x2026"           , true  },
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    { L"012\x05e9\x05bc\x05c1\x05b8", L"012\x2026\x200E"          , true  },
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { L"012\xF0\x9D\x84\x9E",         L"012\xF0\x2026"            , true  },
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<RenderText> expected_render_text(RenderText::CreateInstance());
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  expected_render_text->SetFontList(FontList("serif, Sans serif, 12px"));
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  expected_render_text->SetDisplayRect(Rect(0, 0, 9999, 100));
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetFontList(FontList("serif, Sans serif, 12px"));
46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  render_text->SetElideBehavior(ELIDE_TAIL);
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Compute expected width
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expected_render_text->SetText(WideToUTF16(cases[i].layout_text));
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int expected_width = expected_render_text->GetContentWidth();
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::string16 input = WideToUTF16(cases[i].text);
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Extend the input text to ensure that it is wider than the layout_text,
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // and so it will get elided.
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (cases[i].elision_expected)
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      input.append(WideToUTF16(L" MMMMMMMMMMM"));
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    render_text->SetText(input);
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    render_text->SetDisplayRect(Rect(0, 0, expected_width, 100));
484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(input, render_text->text())
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        << "->For case " << i << ": " << cases[i].text << "\n";
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(WideToUTF16(cases[i].layout_text), render_text->GetLayoutText())
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << "->For case " << i << ": " << cases[i].text << "\n";
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expected_render_text->SetText(base::string16());
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(RenderTextTest, ElidedObscuredText) {
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<RenderText> expected_render_text(RenderText::CreateInstance());
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  expected_render_text->SetFontList(FontList("serif, Sans serif, 12px"));
495010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  expected_render_text->SetDisplayRect(Rect(0, 0, 9999, 100));
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  expected_render_text->SetText(WideToUTF16(L"**\x2026"));
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetFontList(FontList("serif, Sans serif, 12px"));
50046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  render_text->SetElideBehavior(ELIDE_TAIL);
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetDisplayRect(
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      Rect(0, 0, expected_render_text->GetContentWidth(), 100));
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetObscured(true);
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdef"));
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(WideToUTF16(L"abcdef"), render_text->text());
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(WideToUTF16(L"**\x2026"), render_text->GetLayoutText());
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedText) {
510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  struct {
511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const wchar_t* text;
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const wchar_t* layout_text;
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } cases[] = {
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Strings shorter than the truncation length should be laid out in full.
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"",        L""        },
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kWeak,      kWeak      },
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtr,       kLtr       },
518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtrRtl,    kLtrRtl    },
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kLtrRtlLtr, kLtrRtlLtr },
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtl,       kRtl       },
521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtlLtr,    kRtlLtr    },
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { kRtlLtrRtl, kRtlLtrRtl },
523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Strings as long as the truncation length should be laid out in full.
524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01234",   L"01234"   },
525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Long strings should be truncated with an ellipsis appended at the end.
526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012345",                  L"0123\x2026"     },
527558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L" . ",              L"012 \x2026"     },
528558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"abc",              L"012a\x2026"     },
529558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"a" L"\x5d0\x5d1",  L"012a\x2026"     },
530558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"a" L"\x5d1" L"b",  L"012a\x2026"     },
531558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0\x5d1\x5d2",  L"012\x5d0\x2026" },
532558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0\x5d1" L"a",  L"012\x5d0\x2026" },
533558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    { L"012" L"\x5d0" L"a" L"\x5d1",    L"012\x5d0\x2026" },
534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Surrogate pairs should be truncated reasonably enough.
535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0123\x0915\x093f",              L"0123\x2026"                },
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0\x05e9\x05bc\x05c1\x05b8",     L"0\x05e9\x05bc\x05c1\x05b8" },
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01\x05e9\x05bc\x05c1\x05b8",    L"01\x05e9\x05bc\x2026"      },
538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012\x05e9\x05bc\x05c1\x05b8",   L"012\x05e9\x2026"           },
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"0123\x05e9\x05bc\x05c1\x05b8",  L"0123\x2026"                },
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"01234\x05e9\x05bc\x05c1\x05b8", L"0123\x2026"                },
541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { L"012\xF0\x9D\x84\x9E",           L"012\xF0\x2026"             },
542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(5);
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    render_text->SetText(WideToUTF16(cases[i].text));
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(WideToUTF16(cases[i].text), render_text->text());
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(WideToUTF16(cases[i].layout_text), render_text->GetLayoutText())
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        << "For case " << i << ": " << cases[i].text;
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedObscuredText) {
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(3);
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetObscured(true);
558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"abcdef"));
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(WideToUTF16(L"abcdef"), render_text->text());
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(WideToUTF16(L"**\x2026"), render_text->GetLayoutText());
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedCursorMovementLTR) {
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(2);
566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"abcd"));
567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model());
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SelectionModel> expected;
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
577558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The cursor hops over the ellipsis and elided text to the line end.
578558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.clear();
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The cursor hops over the elided text to preceeding text.
585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(RenderTextTest, TruncatedCursorMovementRTL) {
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->set_truncate_length(2);
594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3"));
595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(4, CURSOR_FORWARD), render_text->selection_model());
599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(SelectionModel(0, CURSOR_BACKWARD), render_text->selection_model());
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<SelectionModel> expected;
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
605558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The cursor hops over the ellipsis and elided text to the line end.
606558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.clear();
611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The cursor hops over the elided text to preceeding text.
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetTextDirection) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* text;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection text_direction;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Blank strings and those with no/weak directionality default to LTR.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { L"",        base::i18n::LEFT_TO_RIGHT },
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kWeak,      base::i18n::LEFT_TO_RIGHT },
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong LTR characters.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtr,       base::i18n::LEFT_TO_RIGHT },
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtl,    base::i18n::LEFT_TO_RIGHT },
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLtrRtlLtr, base::i18n::LEFT_TO_RIGHT },
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Strings that begin with strong RTL characters.
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtl,       base::i18n::RIGHT_TO_LEFT },
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtr,    base::i18n::RIGHT_TO_LEFT },
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRtlLtrRtl, base::i18n::RIGHT_TO_LEFT },
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Toggle the application default text direction (to try each direction).
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::i18n::TextDirection ui_direction = base::i18n::IsRTL() ?
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that directionality modes yield the correct text directions.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j].text));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), cases[j].text_direction);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), ui_direction);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_RTL);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that text changes update the direction for DIRECTIONALITY_FROM_TEXT.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kLtr));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::LEFT_TO_RIGHT);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(kRtl));
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->GetTextDirection(), base::i18n::RIGHT_TO_LEFT);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtr) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure LTR.
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abc"));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |expected| saves the expected SelectionModel when moving cursor from left
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to right.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtl) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last one is the expected END position.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInLtrRtlLtr) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR-RTL-LTR.
725558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"a" L"\x05d1" L"b"));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtl) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pure RTL.
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"));
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtr) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR
770558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05d0\x05d1\x05d2" L"abc"));
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_FORWARD));
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_FORWARD));
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_FORWARD));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(4, CURSOR_BACKWARD));
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(5, CURSOR_BACKWARD));
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(6, CURSOR_BACKWARD));
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRightInRtlLtrRtl) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL-LTR-RTL.
798558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05d0" L"a" L"\x05d1"));
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SelectionModel> expected;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_BACKWARD));
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(1, CURSOR_FORWARD));
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_BACKWARD));
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_LEFT);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.clear();
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(3, CURSOR_FORWARD));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_FORWARD));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(2, CURSOR_BACKWARD));
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_FORWARD));
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back(SelectionModel(0, CURSOR_BACKWARD));
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunMoveCursorLeftRightTest(render_text.get(), expected, CURSOR_RIGHT);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): temporarily disable in platform Win since the complex script
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// characters turned into empty square due to font regression. So, not able
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test 2 characters belong to the same grapheme.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4U, render_text->cursor_position());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Enable for RenderTextHarfBuzz. http://crbug.com/383265
8477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(RenderTextTest, MoveCursorLeftRight_MeiryoUILigatures) {
8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateNativeInstance());
8497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Meiryo UI uses single-glyph ligatures for 'ff' and 'ffi', but each letter
8507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // (code point) has unique bounds, so mid-glyph cursoring should be possible.
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  render_text->SetFontList(FontList("Meiryo UI, 12px"));
8527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"ff ffi"));
8537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
8547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (size_t i = 0; i < render_text->text().length(); ++i) {
8557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
8567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(i + 1, render_text->cursor_position());
8577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
8587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
8597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
8607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GraphemePositions) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR abc, LTR 2-character grapheme.
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kText1 =
864558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0915\x093f" L"abc" L"\x0915\x093f");
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, LTR 2-character grapheme, LTR cd.
867558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::string16 kText2 = WideToUTF16(L"ab" L"\x0915\x093f" L"cd");
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // two characters forming the surrogate pair 0x0001D11E.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSurrogate = "\xF0\x9D\x84\x9E";
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR ab, UTF16 surrogate pair, LTR cd.
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kText3 = UTF8ToUTF16("ab" + kSurrogate + "cd");
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t index;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_previous;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_next;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 0, 0, 0 },
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 1, 0, 0 },
884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), 50, 0, 0 },
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 0, 0, 2 },
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 1, 0, 2 },
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 2, 0, 3 },
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 3, 2, 4 },
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 4, 3, 5 },
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 5, 4, 7 },
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 6, 5, 7 },
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 7, 5, 7 },
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 8, 7, 7 },
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText1, 50, 7, 7 },
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 0, 0, 1 },
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 1, 0, 2 },
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 2, 1, 4 },
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 3, 2, 4 },
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 4, 2, 5 },
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 5, 4, 6 },
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 6, 5, 6 },
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 7, 6, 6 },
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText2, 50, 6, 6 },
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 0, 0, 1 },
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 1, 0, 2 },
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 2, 1, 4 },
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 3, 2, 4 },
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 4, 2, 5 },
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 5, 4, 6 },
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 6, 5, 6 },
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 7, 6, 6 },
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kText3, 50, 6, 6 },
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
916010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(msw): XP fails due to lack of font support: http://crbug.com/106450
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
923010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Testing cases[%" PRIuS "]", i));
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t next = render_text->IndexOfAdjacentGrapheme(cases[i].index,
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       CURSOR_FORWARD);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_next, next);
929010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_TRUE(render_text->IsValidCursorIndex(next));
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t previous = render_text->IndexOfAdjacentGrapheme(cases[i].index,
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           CURSOR_BACKWARD);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(cases[i].expected_previous, previous);
934010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_TRUE(render_text->IsValidCursorIndex(previous));
935010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
936010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
937010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
938010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(RenderTextTest, MidGraphemeSelectionBounds) {
939010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if defined(OS_WIN)
940010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(msw): XP fails due to lack of font support: http://crbug.com/106450
941010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
942010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
943010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
944010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
945010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Test that selection bounds may be set amid multi-character graphemes.
946010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const base::string16 kHindi = WideToUTF16(L"\x0915\x093f");
947010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const base::string16 kThai = WideToUTF16(L"\x0e08\x0e33");
948010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const base::string16 cases[] = { kHindi, kThai };
949010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
950010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
951010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); i++) {
952010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Testing cases[%" PRIuS "]", i));
953010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    render_text->SetText(cases[i]);
954010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_TRUE(render_text->IsValidLogicalIndex(1));
955010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#if !defined(OS_MACOSX)
956010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_FALSE(render_text->IsValidCursorIndex(1));
957010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
958010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_TRUE(render_text->SelectRange(Range(2, 1)));
959010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_EQ(Range(2, 1), render_text->selection());
960010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_EQ(1U, render_text->cursor_position());
961010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Although selection bounds may be set within a multi-character grapheme,
962010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // cursor movement (e.g. via arrow key) should avoid those indices.
963010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
964010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_EQ(0U, render_text->cursor_position());
965010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
966010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EXPECT_EQ(2U, render_text->cursor_position());
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
970cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RenderTextTest, FindCursorPosition) {
971cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const wchar_t* kTestStrings[] = { kLtrRtl, kLtrRtlLtr, kRtlLtr, kRtlLtrRtl };
972cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
973cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 100, 20));
974cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
975cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i));
976cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
977cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for(size_t j = 0; j < render_text->text().length(); ++j) {
978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const Range range(render_text->GetGlyphBounds(j));
979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Test a point just inside the leading edge of the glyph bounds.
980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int x = range.is_reversed() ? range.GetMax() - 1 : range.GetMin() + 1;
981cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EXPECT_EQ(j, render_text->FindCursorPosition(Point(x, 0)).caret_pos());
982cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
983cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, EdgeSelectionModels) {
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simple Latin text.
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kLatin = WideToUTF16(L"abc");
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme.
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f");
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LTR 2-character grapheme, LTR a, LTR 2-character grapheme.
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kHindiLatin =
993558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0915\x093f" L"a" L"\x0915\x093f");
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme.
995868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kRTLGrapheme = WideToUTF16(L"\x05e0\x05b8");
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RTL 2-character grapheme, LTR a, RTL 2-character grapheme.
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const base::string16 kHebrewLatin =
998558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x05e0\x05b8" L"a" L"\x05e0\x05b8");
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::i18n::TextDirection expected_text_direction;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    { base::string16(), base::i18n::LEFT_TO_RIGHT },
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLatin,       base::i18n::LEFT_TO_RIGHT },
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kLTRGrapheme, base::i18n::LEFT_TO_RIGHT },
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHindiLatin,  base::i18n::LEFT_TO_RIGHT },
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kRTLGrapheme, base::i18n::RIGHT_TO_LEFT },
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kHebrewLatin, base::i18n::RIGHT_TO_LEFT },
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1013010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // TODO(msw): XP fails due to lack of font support: http://crbug.com/106450
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->SetText(cases[i].text);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ltr = (cases[i].expected_text_direction == base::i18n::LEFT_TO_RIGHT);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start_edge =
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_LEFT : CURSOR_RIGHT);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(start_edge, SelectionModel(0, CURSOR_BACKWARD));
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end_edge =
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->EdgeSelectionModel(ltr ? CURSOR_RIGHT : CURSOR_LEFT);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end_edge, SelectionModel(cases[i].text.length(), CURSOR_FORWARD));
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SelectAll) {
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* const cases[] =
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl, kRtlLtr, kRtlLtrRtl };
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that SelectAll respects the |reversed| argument regardless of
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // application locale and text content directionality.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1040d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SelectionModel expected_reversed(Range(3, 0), CURSOR_FORWARD);
1041d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const SelectionModel expected_forwards(Range(0, 3), CURSOR_BACKWARD);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < 2; ++i) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRTL(!base::i18n::IsRTL());
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test that an empty string produces an empty selection model.
1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    render_text->SetText(base::string16());
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(render_text->selection_model(), SelectionModel());
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the weak, LTR, RTL, and Bidi string cases.
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(cases); j++) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(WideToUTF16(cases[j]));
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(false);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_forwards);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SelectAll(true);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(render_text->selection_model(), expected_reversed);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1063116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) {
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Left arrow on select ranging (6, 4).
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
1068d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
1070d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
1072d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(5), render_text->selection());
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
1074d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
1076d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6, 5), render_text->selection());
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, true);
1078d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6, 4), render_text->selection());
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
1080d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(6), render_text->selection());
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Right arrow on select ranging (4, 6).
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
1084d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(0), render_text->selection());
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1086d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(1), render_text->selection());
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1088d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(2), render_text->selection());
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1090d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(3), render_text->selection());
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1092d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(5), render_text->selection());
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1094d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
1096d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4, 5), render_text->selection());
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, true);
1098d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4, 6), render_text->selection());
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
1100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(Range(4), render_text->selection());
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, CenteredDisplayOffset) {
11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefghij"));
11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_CENTER);
11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int kEnlargement = 10;
11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int content_width = render_text->GetContentWidth();
11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Rect display_rect(0, 0, content_width / 2,
11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    render_text->font_list().GetHeight());
11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Move the cursor to the beginning of the text and, by checking the cursor
11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // bounds, make sure no empty space is to the left of the text.
11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetCursorPosition(0);
11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(display_rect.x(), render_text->GetUpdatedCursorBounds().x());
11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Widen the display rect and, by checking the cursor bounds, make sure no
11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // empty space is introduced to the left of the text.
11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  display_rect.Inset(0, 0, -kEnlargement, 0);
11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(display_rect.x(), render_text->GetUpdatedCursorBounds().x());
11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Move the cursor to the end of the text and, by checking the cursor bounds,
11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // make sure no empty space is to the right of the text.
11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetCursorPosition(render_text->text().length());
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(display_rect.right(),
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Widen the display rect and, by checking the cursor bounds, make sure no
11325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // empty space is introduced to the right of the text.
11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  display_rect.Inset(0, 0, -kEnlargement, 0);
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(display_rect.right(),
11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xji): Make these work on Windows.
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MoveLeftRightByWordVerifier(RenderText* render_text,
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const wchar_t* str) {
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(str));
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from left ro right.
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first_word = true;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, test moving by word from a word break position, such as from
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "|abc def" to "abc| def".
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For testing simplicity, each word is a 3-character word.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then, test moving by word from positions inside the word, such as from
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "a|bc def" to "abc| def", and from "ab|c def" to "abc| def".
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_RIGHT, false);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test moving by word from right to left.
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_word = true;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel start = render_text->selection_model();
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel end = render_text->selection_model();
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (end == start)  // reach the end.
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_of_character_moves = first_word ? 3 : 4;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    first_word = false;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_text->MoveCursorTo(start);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < num_of_character_moves; ++j)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(end, render_text->selection_model());
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 1; j < num_of_character_moves; ++j) {
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursorTo(start);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int k = 0; k < j; ++k)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_text->MoveCursor(CHARACTER_BREAK, CURSOR_LEFT, false);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(end, render_text->selection_model());
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText) {
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For testing simplicity, each word is a 3-character word.
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const wchar_t*> test;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc");
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def");
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3");
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3");
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc \x05E1\x05E2\x05E3 hij");
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 hij opq");
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
1221558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                 L" \x05E7\x05E8\x05E9" L" opq rst uvw");
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 abc");
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 abc def");
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 \x05E7\x05E8\x05E9"
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij");
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 abc \x05E1\x05E2\x05E3");
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 abc def"
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6");
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 \x05D7\x05D8\x05D9"
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 L" \x05E7\x05E8\x05E9");
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test.size(); ++i)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MoveLeftRightByWordVerifier(render_text.get(), test[i]);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"ab\x05E1"));
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "abC|" to the left should return "|abC".
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "ab|C".
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|abC" to the right returns "abC|".
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1256558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(WideToUTF16(L"\x05E1\x05E2" L"a"));
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For logical text "BCa", moving the cursor by word from "aCB|" to the left
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns "|aCB".
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_RIGHT, false);
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SelectionModel(3, CURSOR_FORWARD), render_text->selection_model());
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Moving the cursor by word from "|aCB" to the right should return "aCB|".
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But since end of text is always treated as a word break, it returns
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // position "a|CB".
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(xji): Need to make it work as expected.
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EXPECT_EQ(SelectionModel(), render_text->selection_model());
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abc     def"));
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(11U, render_text->cursor_position());
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(5, CURSOR_FORWARD));
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_LEFT, false);
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x6211\x4EEC\x53BB\x516C\x56ED\x73A9"));
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(LINE_BREAK, CURSOR_LEFT, false);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, render_text->cursor_position());
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, render_text->cursor_position());
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, render_text->cursor_position());
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, render_text->cursor_position());
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursor(WORD_BREAK, CURSOR_RIGHT, false);
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, render_text->cursor_position());
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Remove when RenderTextWin goes away.
1303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#if defined(OS_WIN)
1304558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(RenderTextTest, Win_LogicalClusters) {
1305558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<RenderTextWin> render_text(
13065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
1307558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1308558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const base::string16 test_string =
1309558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      WideToUTF16(L"\x0930\x0930\x0930\x0930\x0930");
1310558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->SetText(test_string);
1311558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->EnsureLayout();
1312558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ASSERT_EQ(1U, render_text->runs_.size());
1313558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  WORD* logical_clusters = render_text->runs_[0]->logical_clusters.get();
1314558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (size_t i = 0; i < test_string.length(); ++i)
1315558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    EXPECT_EQ(i, logical_clusters[i]);
1316558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
1317558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif  // defined(OS_WIN)
1318558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeSanity) {
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Size string_size = render_text->GetStringSize();
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.width(), 0);
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(string_size.height(), 0);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1327116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(RenderTextTest, StringSizeLongStrings) {
1328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Size previous_string_size;
1330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t length = 10; length < 1000000; length *= 10) {
1331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    render_text->SetText(base::string16(length, 'a'));
1332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Size string_size = render_text->GetStringSize();
1333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_GT(string_size.width(), previous_string_size.width());
1334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_GT(string_size.height(), 0);
1335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    previous_string_size = string_size;
1336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
1338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): This test fails because PlatformFontMac uses point font
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  sizes instead of pixel sizes like other implementations.
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeEmptyString) {
1343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Ascent and descent of Arial and Symbol are different on most platforms.
1344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FontList font_list("Arial,Symbol, 16px");
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(font_list);
13470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 0, font_list.GetHeight()));
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The empty string respects FontList metrics for non-zero height
1350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and baseline.
1351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  render_text->SetText(base::string16());
1352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetStringSize().width());
1354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16(" "));
1357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Check that Arial and Symbol have different font metrics.
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font arial_font("Arial", 16);
1365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ("arial",
13666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            base::StringToLowerASCII(arial_font.GetActualFontNameForTesting()));
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font symbol_font("Symbol", 16);
1368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ("symbol",
13696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            base::StringToLowerASCII(
13706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                symbol_font.GetActualFontNameForTesting()));
1371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_NE(arial_font.GetHeight(), symbol_font.GetHeight());
1372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_NE(arial_font.GetBaseline(), symbol_font.GetBaseline());
1373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // "a" should be rendered with Arial, not with Symbol.
1374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* arial_font_text = "a";
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // "®" (registered trademark symbol) should be rendered with Symbol,
1376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // not with Arial.
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* symbol_font_text = "\xC2\xAE";
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font smaller_font = arial_font;
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Font larger_font = symbol_font;
1381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* smaller_font_text = arial_font_text;
1382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* larger_font_text = symbol_font_text;
1383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (symbol_font.GetHeight() < arial_font.GetHeight() &&
1384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      symbol_font.GetBaseline() < arial_font.GetBaseline()) {
1385a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::swap(smaller_font, larger_font);
1386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::swap(smaller_font_text, larger_font_text);
1387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_LT(smaller_font.GetHeight(), larger_font.GetHeight());
1389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_LT(smaller_font.GetBaseline(), larger_font.GetBaseline());
1390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Check |smaller_font_text| is rendered with the smaller font.
1392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16(smaller_font_text));
13940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetFontList(FontList(smaller_font));
13950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 0,
13960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                   render_text->font_list().GetHeight()));
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(smaller_font.GetHeight(), render_text->GetStringSize().height());
1398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(smaller_font.GetBaseline(), render_text->GetBaseline());
1399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Layout the same text with mixed fonts.  The text should be rendered with
1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the smaller font, but the height and baseline are determined with the
1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // metrics of the font list, which is equal to the larger font.
1403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<Font> fonts;
1404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fonts.push_back(smaller_font);  // The primary font is the smaller font.
1405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fonts.push_back(larger_font);
1406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FontList font_list(fonts);
1407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(font_list);
14080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetDisplayRect(Rect(0, 0, 0,
14090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                   render_text->font_list().GetHeight()));
1410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_LT(smaller_font.GetHeight(), render_text->GetStringSize().height());
1411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_LT(smaller_font.GetBaseline(), render_text->GetBaseline());
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
1414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(RenderTextTest, SetFontList) {
1417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetFontList(FontList("Arial,Symbol, 13px"));
1419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const std::vector<Font>& fonts = render_text->font_list().GetFonts();
1420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(2U, fonts.size());
1421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ("Arial", fonts[0].GetFontName());
1422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ("Symbol", fonts[1].GetFontName());
14235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(13, render_text->font_list().GetFontSize());
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeBoldWidth) {
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_width = render_text->GetStringSize().width();
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_width, 0);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply a bold style and check that the new width is greater.
14347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  render_text->SetStyle(BOLD, true);
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int bold_width = render_text->GetStringSize().width();
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(bold_width, plain_width);
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, apply a plain style over the first word only.
1439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->ApplyStyle(BOLD, false, Range(0, 5));
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int plain_bold_width = render_text->GetStringSize().width();
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(plain_bold_width, plain_width);
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(plain_bold_width, bold_width);
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, StringSizeHeight) {
1446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::string16 cases[] = {
14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"Hello World!"),  // English
14482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x6328\x62f6"),  // Japanese
14492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x0915\x093f"),  // Hindi
14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WideToUTF16(L"\x05e0\x05b8"),  // Hebrew
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const FontList default_font_list;
14545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const FontList& larger_font_list = default_font_list.DeriveWithSizeDelta(24);
14555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_GT(larger_font_list.GetHeight(), default_font_list.GetHeight());
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    render_text->SetFontList(default_font_list);
14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    render_text->SetText(cases[i]);
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height1 = render_text->GetStringSize().height();
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height1, 0);
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check that setting the larger font increases the height.
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    render_text->SetFontList(larger_font_list);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int height2 = render_text->GetStringSize().height();
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(height2, height1);
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, GetBaselineSanity) {
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(UTF8ToUTF16("Hello World"));
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int baseline = render_text->GetBaseline();
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(baseline, 0);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, CursorBoundsInReplacementMode) {
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(100, 17));
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_b(1, CURSOR_FORWARD);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectionModel sel_c(2, CURSOR_FORWARD);
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_around_b = render_text->GetCursorBounds(sel_b, false);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_b = render_text->GetCursorBounds(sel_b, true);
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Rect cursor_before_c = render_text->GetCursorBounds(sel_c, true);
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.x(), cursor_before_b.x());
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cursor_around_b.right(), cursor_before_c.x());
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffset) {
149390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The default horizontal text offset differs for LTR and RTL, and is only set
149490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // when the RenderText object is created.  This test will check the default in
149590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // LTR mode, and the next test will check the RTL default.
149690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
149790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(false);
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set display area's size equal to the font size.
15037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const Size font_size(render_text->GetContentWidth(),
15040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       render_text->font_list().GetHeight());
150590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Vector2d offset = render_text->GetLineOffset(0);
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(offset.IsZero());
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const int kEnlargementX = 2;
15120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  display_rect.Inset(0, 0, -kEnlargementX, 0);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Check the default horizontal alignment.
1516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
151790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check explicitly setting the horizontal alignment.
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_LEFT);
1521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
152290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0, offset.x());
152390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_CENTER);
1524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
15250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(kEnlargementX / 2, offset.x());
152690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetHorizontalAlignment(ALIGN_RIGHT);
1527d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
15280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(kEnlargementX, offset.x());
152990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Check that text is vertically centered within taller display rects.
15310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const int kEnlargementY = display_rect.height();
15320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  display_rect.Inset(0, 0, 0, -kEnlargementY);
15330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
15340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const Vector2d prev_offset = render_text->GetLineOffset(0);
15350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  display_rect.Inset(0, 0, 0, -2 * kEnlargementY);
15360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetDisplayRect(display_rect);
1537d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  offset = render_text->GetLineOffset(0);
15380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(prev_offset.y() + kEnlargementY, offset.y());
153990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
154190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
154290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(RenderTextTest, GetTextOffsetHorizontalDefaultInRTL) {
154490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This only checks the default horizontal alignment in RTL mode; all other
1545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // GetLineOffset(0) attributes are checked by the test above.
154690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
154790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(true);
154890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
154990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
155090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetFontList(FontList("Arial, 13px"));
155190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kEnlargement = 2;
15527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const Size font_size(render_text->GetContentWidth() + kEnlargement,
15537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       render_text->GetStringSize().height());
155490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Rect display_rect(font_size);
155590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  render_text->SetDisplayRect(display_rect);
1556d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Vector2d offset = render_text->GetLineOffset(0);
155790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(kEnlargement, offset.x());
155890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetRTL(was_rtl);
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1561116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(RenderTextTest, SetDisplayOffset) {
1562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  render_text->SetText(ASCIIToUTF16("abcdefg"));
1564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  render_text->SetFontList(FontList("Arial, 13px"));
1565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const Size font_size(render_text->GetContentWidth(),
1567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                       render_text->font_list().GetHeight());
1568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const int kEnlargement = 10;
1569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Set display width |kEnlargement| pixels greater than content width and test
1571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // different possible situations. In this case the only possible display
1572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // offset is zero.
1573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Rect display_rect(font_size);
1574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  display_rect.Inset(0, 0, -kEnlargement, 0);
1575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  render_text->SetDisplayRect(display_rect);
1576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  struct {
1578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    HorizontalAlignment alignment;
1579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int offset;
1580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } small_content_cases[] = {
1581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, -kEnlargement },
1582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, 0 },
1583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, kEnlargement },
1584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, -kEnlargement },
1585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, 0 },
1586116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, kEnlargement },
1587116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_CENTER, -kEnlargement },
1588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_CENTER, 0 },
1589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_CENTER, kEnlargement },
1590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
1591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(small_content_cases); i++) {
1593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    render_text->SetHorizontalAlignment(small_content_cases[i].alignment);
1594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    render_text->SetDisplayOffset(small_content_cases[i].offset);
1595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_EQ(0, render_text->GetUpdatedDisplayOffset().x());
1596116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1598116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Set display width |kEnlargement| pixels less than content width and test
1599116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // different possible situations.
1600116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  display_rect = Rect(font_size);
1601116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  display_rect.Inset(0, 0, kEnlargement, 0);
1602116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  render_text->SetDisplayRect(display_rect);
1603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1604116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  struct {
1605116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    HorizontalAlignment alignment;
1606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int offset;
1607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int expected_offset;
1608116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } large_content_cases[] = {
1609116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // When text is left-aligned, display offset can be in range
1610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // [-kEnlargement, 0].
1611116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, -2 * kEnlargement, -kEnlargement },
1612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, -kEnlargement / 2, -kEnlargement / 2 },
1613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_LEFT, kEnlargement, 0 },
1614116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // When text is right-aligned, display offset can be in range
1615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // [0, kEnlargement].
1616116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, -kEnlargement, 0 },
1617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, kEnlargement / 2, kEnlargement / 2 },
1618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_RIGHT, 2 * kEnlargement, kEnlargement },
1619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // When text is center-aligned, display offset can be in range
16205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // [-kEnlargement / 2 - 1, (kEnlargement - 1) / 2].
16215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { ALIGN_CENTER, -kEnlargement, -kEnlargement / 2 - 1 },
1622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_CENTER, -kEnlargement / 4, -kEnlargement / 4 },
1623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    { ALIGN_CENTER, kEnlargement / 4, kEnlargement / 4 },
16245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { ALIGN_CENTER, kEnlargement, (kEnlargement - 1) / 2 },
1625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
1626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(large_content_cases); i++) {
1628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    render_text->SetHorizontalAlignment(large_content_cases[i].alignment);
1629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    render_text->SetDisplayOffset(large_content_cases[i].offset);
1630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_EQ(large_content_cases[i].expected_offset,
1631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              render_text->GetUpdatedDisplayOffset().x());
1632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
1634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, SameFontForParentheses) {
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
16375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::char16 left_char;
16385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::char16 right_char;
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } punctuation_pairs[] = {
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '(', ')' },
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '{', '}' },
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { '<', '>' },
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)") },
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(English)English
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(a)Hello World") },
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)") },
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Japanese(English)Japanese
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x6328\x62f6(a)\x6328\x62f6") },
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Japanese)English
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x6328\x62f6)Hello World") },
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)") },
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hindi(English)Hindi
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x0915\x093f(a)\x0915\x093f") },
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hindi)English
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x0915\x093f)Hello World") },
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)") },
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hebrew(English)Hebrew
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"\x05e0\x05b8(a)\x05e0\x05b8") },
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // English(Hebrew)English
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { WideToUTF16(L"Hello World(\x05e0\x05b8)Hello World") },
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::string16 text = cases[i].text;
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t start_paren_char_index = text.find('(');
1678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_NE(base::string16::npos, start_paren_char_index);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t end_paren_char_index = text.find(')');
1680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_NE(base::string16::npos, end_paren_char_index);
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(punctuation_pairs); ++j) {
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[start_paren_char_index] = punctuation_pairs[j].left_char;
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text[end_paren_char_index] = punctuation_pairs[j].right_char;
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_text->SetText(text);
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<RenderText::FontSpan> spans =
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          render_text->GetFontSpansForTesting();
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int start_paren_span_index = -1;
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int end_paren_span_index = -1;
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t k = 0; k < spans.size(); ++k) {
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, start_paren_char_index))
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          start_paren_span_index = k;
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IndexInRange(spans[k].second, end_paren_char_index))
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          end_paren_span_index = k;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, start_paren_span_index);
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_NE(-1, end_paren_span_index);
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& start_font = spans[start_paren_span_index].first;
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Font& end_font = spans[end_paren_span_index].first;
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontName(), end_font.GetFontName());
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetFontSize(), end_font.GetFontSize());
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(start_font.GetStyle(), end_font.GetStyle());
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure the caret width is always >=1 so that the correct
17112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// caret is drawn at high DPI. crbug.com/164100.
17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RenderTextTest, CaretWidth) {
17132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
17142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16("abcdefg"));
17152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_GE(render_text->GetUpdatedCursorBounds().width(), 1);
17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1718a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(RenderTextTest, SelectWord) {
1719a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  render_text->SetText(ASCIIToUTF16(" foo  a.bc.d bar"));
1721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  struct {
1723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t cursor;
1724a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t selection_start;
1725a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    size_t selection_end;
1726a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  } cases[] = {
1727a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 0,   0,  1 },
1728a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 1,   1,  4 },
1729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 2,   1,  4 },
1730a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 3,   1,  4 },
1731a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 4,   4,  6 },
1732a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 5,   4,  6 },
1733a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 6,   6,  7 },
1734a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 7,   7,  8 },
1735a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 8,   8, 10 },
1736a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 9,   8, 10 },
1737a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 10, 10, 11 },
1738a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 11, 11, 12 },
1739a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 12, 12, 13 },
1740a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 13, 13, 16 },
1741a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 14, 13, 16 },
1742a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 15, 13, 16 },
1743a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { 16, 13, 16 },
1744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
1745a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1746a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1747a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SetCursorPosition(cases[i].cursor);
1748a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SelectWord();
1749d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(Range(cases[i].selection_start, cases[i].selection_end),
1750a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              render_text->selection());
1751a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1752a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1753a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Make sure the last word is selected when the cursor is at text.length().
1755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(RenderTextTest, LastWordSelected) {
1756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL1 = "http://www.google.com";
1757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string kTestURL2 = "http://www.google.com/something/";
1758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL1));
1762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL1.length());
1763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1764a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("com"), GetSelectedText(render_text.get()));
1765a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL2));
1768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SetCursorPosition(kTestURL2.length());
1769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  render_text->SelectWord();
1770a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("/"), GetSelectedText(render_text.get()));
1771a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1772a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
1773a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1774a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// When given a non-empty selection, SelectWord should expand the selection to
1775a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// nearest word boundaries.
1776a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)TEST_F(RenderTextTest, SelectMultipleWords) {
1777a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string kTestURL = "http://www.google.com";
1778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1779a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1780a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1781a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SetText(ASCIIToUTF16(kTestURL));
1782d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SelectRange(Range(16, 20));
1783a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1784a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1785a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(render_text->selection().is_reversed());
1786a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1787a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // SelectWord should preserve the selection direction.
1788d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SelectRange(Range(20, 16));
1789a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  render_text->SelectWord();
1790a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ASCIIToUTF16("google.com"), GetSelectedText(render_text.get()));
1791a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_TRUE(render_text->selection().is_reversed());
1792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): Cursor movements tests disabled on Mac because RenderTextMac
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                  does not implement this yet. http://crbug.com/131618
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorLTR) {
17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::IsRTL());
17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(base::i18n::ICUIsRTL());
18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
1814a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
1819a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
1820a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
1839a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
1844a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width(),
1845a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().right());
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(width, render_text->GetUpdatedCursorBounds().x());
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RenderTextTest, DisplayRectShowsCursorRTL) {
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the application default text direction to RTL.
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool was_rtl = base::i18n::IsRTL();
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(true);
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"abcdefghijklmnopqrstuvwxzyabcdefg"));
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width = render_text->GetStringSize().width();
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeat the test with RTL text.
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7"
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      L"\x5d8\x5d9\x5da\x5db\x5dc\x5dd\x5de\x5df"));
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->MoveCursorTo(SelectionModel(render_text->text().length(),
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           CURSOR_FORWARD));
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = render_text->GetStringSize().width();
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(width, 10);
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the cursor is placed at the width of its preceding text.
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that shrinking the display rectangle keeps the cursor in view.
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 10, 1));
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the text will pan to fill its expanding display rectangle.
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width - 5, 1));
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, render_text->GetUpdatedCursorBounds().x());
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that a sufficiently large display rectangle shows all the text.
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_text->SetDisplayRect(Rect(width + 10, 1));
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(render_text->display_rect().width() - width - 1,
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            render_text->GetUpdatedCursorBounds().x());
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the application default text direction to LTR.
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetRTL(was_rtl);
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(was_rtl, base::i18n::IsRTL());
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1913a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Changing colors between or inside ligated glyphs should not break shaping.
1914558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(RenderTextTest, SelectionKeepsLigatures) {
1915cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const wchar_t* kTestStrings[] = { L"\x644\x623", L"\x633\x627" };
1916558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
1917558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  render_text->set_selection_color(SK_ColorRED);
1918a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Canvas canvas;
1919a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1920a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1921a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
1922a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const int expected_width = render_text->GetStringSize().width();
1923d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->MoveCursorTo(SelectionModel(Range(0, 1), CURSOR_FORWARD));
1924a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    EXPECT_EQ(expected_width, render_text->GetStringSize().width());
1925cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Drawing the text should not DCHECK or crash; see http://crbug.com/262119
1926a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->Draw(&canvas);
1927a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    render_text->MoveCursorTo(SelectionModel(0, CURSOR_FORWARD));
1928a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1929558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
1930558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
193158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_WIN)
19325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline.
1933d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings wrap onto multiple lines for a small available width.
1934d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_MinWidth) {
1935d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const wchar_t* kTestStrings[] = { kWeak, kLtr, kLtrRtl, kLtrRtlLtr, kRtl,
1936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                    kRtlLtr, kRtlLtrRtl };
1937d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1938d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
19395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
1940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(1, 1000));
1941d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1943d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1944d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
1945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
1946d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
1947d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
1948d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_GT(render_text->lines_.size(), 1U);
1949d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1950d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
19525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline.
1953d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings wrap onto multiple lines for a normal available width.
1954d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_NormalWidth) {
1955d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const struct {
1956d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const wchar_t* const text;
1957d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Range first_line_char_range;
1958d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Range second_line_char_range;
1959d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } kTestStrings[] = {
1960d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { L"abc defg hijkl", Range(0, 9), Range(9, 14) },
19614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    { L"qwertyzxcvbn", Range(0, 8), Range(8, 12) },
1962d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD",
1963d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          Range(4, 10), Range(0, 4) }
1964d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
1965d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1966d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
19675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
1968d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(50, 1000));
1969d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1970d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1971d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1972d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) {
1973d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
1974d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i].text));
1975d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
1976d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(2U, render_text->lines_.size());
1977d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(1U, render_text->lines_[0].segments.size());
1978d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kTestStrings[i].first_line_char_range,
1979d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              render_text->lines_[0].segments[0].char_range);
1980d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_EQ(1U, render_text->lines_[1].segments.size());
1981d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kTestStrings[i].second_line_char_range,
1982d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              render_text->lines_[1].segments[0].char_range);
1983d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
1984d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1985d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
19865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline.
1987d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Ensure strings don't wrap onto multiple lines for a sufficient available
1988d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// width.
1989d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST_F(RenderTextTest, Multiline_SufficientWidth) {
1990d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const wchar_t* kTestStrings[] = { L"", L" ", L".", L" . ", L"abc", L"a b c",
1991d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                    L"\x62E\x628\x632", L"\x62E \x628 \x632" };
1992d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1993d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
19945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
1995d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetDisplayRect(Rect(30, 1000));
1996d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  render_text->SetMultiline(true);
1997d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Canvas canvas;
1998d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1999d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2000d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2001d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
2002d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_text->Draw(&canvas);
2003d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(1U, render_text->lines_.size());
2004d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2005d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
20060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
20075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Enable for RenderTextHarfBuzz after implementing multiline.
2008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(RenderTextTest, Multiline_Newline) {
2009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const struct {
2010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const wchar_t* const text;
2011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Ranges of the characters on each line preceding the newline.
2012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Range first_line_char_range;
2013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Range second_line_char_range;
2014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } kTestStrings[] = {
2015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { L"abc\ndef", Range(0, 3), Range(4, 7) },
2016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { L"a \n b ", Range(0, 2), Range(3, 6) },
2017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    { L"\n" , Range::InvalidRange(), Range::InvalidRange() }
2018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  };
2019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
20215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
2022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  render_text->SetDisplayRect(Rect(200, 1000));
2023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  render_text->SetMultiline(true);
2024a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Canvas canvas;
2025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) {
2027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
2028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i].text));
2029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    render_text->Draw(&canvas);
2030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(2U, render_text->lines_.size());
2032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Range first_expected_range = kTestStrings[i].first_line_char_range;
2034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(first_expected_range.IsValid() ? 2U : 1U,
2035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              render_text->lines_[0].segments.size());
2036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (first_expected_range.IsValid())
2037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_EQ(first_expected_range,
2038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                render_text->lines_[0].segments[0].char_range);
2039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2040a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const internal::LineSegment& newline_segment =
2041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        render_text->lines_[0].segments[first_expected_range.IsValid() ? 1 : 0];
2042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(1U, newline_segment.char_range.length());
2043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EXPECT_EQ(L'\n', kTestStrings[i].text[newline_segment.char_range.start()]);
2044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Range second_expected_range = kTestStrings[i].second_line_char_range;
2046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(second_expected_range.IsValid() ? 1U : 0U,
2047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              render_text->lines_[1].segments.size());
2048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (second_expected_range.IsValid())
2049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_EQ(second_expected_range,
2050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                render_text->lines_[1].segments[0].char_range);
2051a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
2052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2053a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
20545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(ckocagil): Remove when RenderTextWin goes away.
20555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, BreakRunsByUnicodeBlocks) {
20560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  scoped_ptr<RenderTextWin> render_text(
20575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<RenderTextWin*>(RenderText::CreateNativeInstance()));
20580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
20590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // The '\x25B6' "play character" should break runs. http://crbug.com/278913
20600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"x\x25B6y"));
20610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->EnsureLayout();
20620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ASSERT_EQ(3U, render_text->runs_.size());
20630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(0, 1), render_text->runs_[0]->range);
20640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(1, 2), render_text->runs_[1]->range);
20650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text->runs_[2]->range);
20660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
20670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->SetText(WideToUTF16(L"x \x25B6 y"));
20680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  render_text->EnsureLayout();
20690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  ASSERT_EQ(3U, render_text->runs_.size());
20700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(0, 2), render_text->runs_[0]->range);
20710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text->runs_[1]->range);
20720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EXPECT_EQ(Range(3, 5), render_text->runs_[2]->range);
20730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
2074d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif  // defined(OS_WIN)
2075d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
20765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Test TextRunHarfBuzz's cluster finding logic.
20775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_Clusters) {
2078f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct {
2079f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    uint32 glyph_to_char[4];
20805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range chars[4];
20815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range glyphs[4];
2082f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool is_rtl;
2083f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } cases[] = {
2084f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    { // From string "A B C D" to glyphs "a b c d".
2085f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { 0, 1, 2, 3 },
20865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) },
2087f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) },
2088f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      false
2089f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    },
20905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { // From string "A B C D" to glyphs "d c b a".
2091f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { 3, 2, 1, 0 },
20925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 1), Range(1, 2), Range(2, 3), Range(3, 4) },
2093f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { Range(3, 4), Range(2, 3), Range(1, 2), Range(0, 1) },
2094f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      true
2095f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    },
2096f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    { // From string "A B C D" to glyphs "ab c c d".
2097f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { 0, 2, 2, 3 },
20985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 2), Range(0, 2), Range(2, 3), Range(3, 4) },
2099f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { Range(0, 1), Range(0, 1), Range(1, 3), Range(3, 4) },
2100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      false
2101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    },
2102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    { // From string "A B C D" to glyphs "d c c ba".
2103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { 3, 2, 2, 0 },
21045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 2), Range(0, 2), Range(2, 3), Range(3, 4) },
2105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      { Range(3, 4), Range(3, 4), Range(1, 3), Range(0, 1) },
2106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      true
2107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    },
2108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
2109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  internal::TextRunHarfBuzz run;
2111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  run.range = Range(0, 4);
2112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  run.glyph_count = 4;
21135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.glyph_to_char.resize(4);
2114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
2116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::copy(cases[i].glyph_to_char, cases[i].glyph_to_char + 4,
21175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              run.glyph_to_char.begin());
2118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    run.is_rtl = cases[i].is_rtl;
21195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t j = 0; j < 4; ++j) {
2121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SCOPED_TRACE(base::StringPrintf("Case %" PRIuS ", char %" PRIuS, i, j));
21225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      Range chars;
21235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      Range glyphs;
21245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      run.GetClusterAt(j, &chars, &glyphs);
21255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_EQ(cases[i].chars[j], chars);
21265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_EQ(cases[i].glyphs[j], glyphs);
21275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_EQ(cases[i].glyphs[j], run.CharRangeToGlyphRange(chars));
21285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
21295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
21305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
21315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Ensure that graphemes with multiple code points do not get split.
21335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemeCases) {
21345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const wchar_t* cases[] = {
21355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // "A" with a combining umlaut, followed by a "B".
21365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    L"A\x0308" L"B",
21375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Devanagari biconsonantal conjunct "ki", followed by an "a".
21385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    L"\x0915\x093f\x0905",
21395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Thai consonant and vowel pair "cho chan" + "sara am", followed by Thai
21405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // digit 0.
21415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    L"\x0e08\x0e33\x0E50",
21425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  };
21435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RenderTextHarfBuzz render_text;
21455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < arraysize(cases); ++i) {
21475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Case %" PRIuS, i));
21485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::string16 text = WideToUTF16(cases[i]);
21505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    render_text.SetText(text);
21515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    render_text.EnsureLayout();
21525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ASSERT_EQ(1U, render_text.runs_.size());
21535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    internal::TextRunHarfBuzz* run = render_text.runs_[0];
21545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::i18n::BreakIterator* iter = render_text.grapheme_iterator_.get();
21565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range first_grapheme_bounds = run->GetGraphemeBounds(iter, 0);
21575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(first_grapheme_bounds, run->GetGraphemeBounds(iter, 1));
21585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range second_grapheme_bounds = run->GetGraphemeBounds(iter, 2);
21595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EXPECT_EQ(first_grapheme_bounds.end(), second_grapheme_bounds.start());
21605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
21615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
21625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Test the partition of a multi-grapheme cluster into grapheme ranges.
21645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_SubglyphGraphemePartition) {
21655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  struct {
21665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32 glyph_to_char[2];
21675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range bounds[4];
21685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool is_rtl;
21695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } cases[] = {
21705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { // From string "A B C D" to glyphs "a bcd".
21715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { 0, 1 },
21725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 10), Range(10, 13), Range(13, 17), Range(17, 20) },
21735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      false
21745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    },
21755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { // From string "A B C D" to glyphs "ab cd".
21765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { 0, 2 },
21775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(0, 5), Range(5, 10), Range(10, 15), Range(15, 20) },
21785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      false
21795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    },
21805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { // From string "A B C D" to glyphs "dcb a".
21815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { 1, 0 },
21825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(10, 20), Range(7, 10), Range(3, 7), Range(0, 3) },
21835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      true
21845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    },
21855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    { // From string "A B C D" to glyphs "dc ba".
21865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { 2, 0 },
21875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      { Range(15, 20), Range(10, 15), Range(5, 10), Range(0, 5) },
21885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      true
21895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    },
21905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  };
21915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  internal::TextRunHarfBuzz run;
21935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.range = Range(0, 4);
21945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.glyph_count = 2;
21955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.glyph_to_char.resize(2);
21965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.positions.reset(new SkPoint[4]);
21975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.width = 20;
21985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::string16 kString = ASCIIToUTF16("abcd");
22005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::i18n::BreakIterator> iter(new base::i18n::BreakIterator(
22015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kString, base::i18n::BreakIterator::BREAK_CHARACTER));
22025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(iter->Init());
22035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
22055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::copy(cases[i].glyph_to_char, cases[i].glyph_to_char + 2,
22065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              run.glyph_to_char.begin());
22075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    run.is_rtl = cases[i].is_rtl;
22085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (int j = 0; j < 2; ++j)
22095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      run.positions[j].set(j * 10, 0);
22105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (size_t j = 0; j < 4; ++j) {
22125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SCOPED_TRACE(base::StringPrintf("Case %" PRIuS ", char %" PRIuS, i, j));
22135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EXPECT_EQ(cases[i].bounds[j], run.GetGraphemeBounds(iter.get(), j));
2214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
2215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
2216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
2217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_RunDirection) {
2219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RenderTextHarfBuzz render_text;
2220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const base::string16 mixed =
2221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      WideToUTF16(L"\x05D0\x05D1" L"1234" L"\x05D2\x05D3");
2222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.SetText(mixed);
2223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.EnsureLayout();
2224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(3U, render_text.runs_.size());
2225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(render_text.runs_[0]->is_rtl);
2226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(render_text.runs_[1]->is_rtl);
2227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(render_text.runs_[2]->is_rtl);
2228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
2229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_BreakRunsByUnicodeBlocks) {
2231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RenderTextHarfBuzz render_text;
2232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // The '\x25B6' "play character" should break runs. http://crbug.com/278913
2234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.SetText(WideToUTF16(L"x\x25B6y"));
2235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.EnsureLayout();
2236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(3U, render_text.runs_.size());
2237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(0, 1), render_text.runs_[0]->range);
2238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(1, 2), render_text.runs_[1]->range);
2239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text.runs_[2]->range);
2240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.SetText(WideToUTF16(L"x \x25B6 y"));
2242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  render_text.EnsureLayout();
2243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(3U, render_text.runs_.size());
2244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(0, 2), render_text.runs_[0]->range);
2245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(2, 3), render_text.runs_[1]->range);
2246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(Range(3, 5), render_text.runs_[2]->range);
2247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
2248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Disabled on Mac because RenderTextMac doesn't implement GetGlyphBounds.
2250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if !defined(OS_MACOSX)
2251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(RenderTextTest, GlyphBounds) {
2252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const wchar_t* kTestStrings[] = {
2253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      L"asdf 1234 qwer", L"\x0647\x0654", L"\x0645\x0631\x062D\x0628\x0627"
2254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
2255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
2256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
2259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    render_text->EnsureLayout();
2260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t j = 0; j < render_text->text().length(); ++j)
2262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      EXPECT_FALSE(render_text->GetGlyphBounds(j).is_empty());
2263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
2264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
2265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
2266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Remove this after making RTHB default in favor of RenderTextTest.GlyphBounds.
2268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_GlyphBounds) {
2269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const wchar_t* kTestStrings[] = {
2270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      L"asdf 1234 qwer", L"\x0647\x0654", L"\x0645\x0631\x062D\x0628\x0627"
2271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
2272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<RenderText> render_text(new RenderTextHarfBuzz);
2273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
2275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    render_text->SetText(WideToUTF16(kTestStrings[i]));
2276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    render_text->EnsureLayout();
2277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t j = 0; j < render_text->text().length(); ++j)
2279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      EXPECT_FALSE(render_text->GetGlyphBounds(j).is_empty());
2280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
2281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
2282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
22835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Ensure that shaping with a non-existent font does not cause a crash.
22845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_NonExistentFont) {
22855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RenderTextHarfBuzz render_text;
22865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text.SetText(ASCIIToUTF16("test"));
22875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text.EnsureLayout();
22885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(1U, render_text.runs_.size());
22895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  internal::TextRunHarfBuzz* run = render_text.runs_[0];
22905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  render_text.ShapeRunWithFont(run, "TheFontThatDoesntExist");
22915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
22925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Ensure an empty run returns sane values to queries.
22945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(RenderTextTest, HarfBuzz_EmptyRun) {
22955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  internal::TextRunHarfBuzz run;
22965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::string16 kString = ASCIIToUTF16("abcdefgh");
22975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::i18n::BreakIterator> iter(new base::i18n::BreakIterator(
22985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kString, base::i18n::BreakIterator::BREAK_CHARACTER));
22995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(iter->Init());
23005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.range = Range(3, 8);
23025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.glyph_count = 0;
23035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(Range(0, 0), run.CharRangeToGlyphRange(Range(4, 5)));
23045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(Range(0, 0), run.GetGraphemeBounds(iter.get(), 4));
23055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range chars;
23065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range glyphs;
23075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run.GetClusterAt(4, &chars, &glyphs);
23085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(Range(3, 8), chars);
23095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(Range(0, 0), glyphs);
23105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
23115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
2313