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