Commit 543f890e authored by thakis@chromium.org's avatar thakis@chromium.org

Revert 113075 (requested by asvitkine) (requested by asvitkine) (requested by...

Revert 113075 (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) (requested by asvitkine) - Improve RenderTextWin font fallback.

Don't use SCRIPT_UNDEFINED in the case of font fallback,
unless font fallback actually fails to return a script
that can display the characters. This fixes the problem
of some scripts not being properly displayed.

This actually makes RenderTextWin properly validate whether
a text position accepts a cursor, which caused several tests
to fail and revealed some additional issues in RenderTextWin.

The CL includes some modifications to address this.

Some tests are disabled under XP, see:
http://crbug.com/106450

Also, fixes some lint warnings.

BUG=90426
TEST=Run chrome.exe --use-pure-views and paste some Bengali
text into the omnibox. It should show up properly.

Review URL: http://codereview.chromium.org/8575020

TBR=asvitkine@chromium.org
Review URL: http://codereview.chromium.org/8819001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113083 0039d316-1c4b-4281-b951-d872f2087c98
parent 9f9fd176
...@@ -67,9 +67,8 @@ void ApplyStyleRangeImpl(gfx::StyleRanges* style_ranges, ...@@ -67,9 +67,8 @@ void ApplyStyleRangeImpl(gfx::StyleRanges* style_ranges,
} else if (i->range.end() > new_range.end()) { } else if (i->range.end() > new_range.end()) {
i->range.set_start(new_range.end()); i->range.set_start(new_range.end());
break; break;
} else { } else
NOTREACHED(); NOTREACHED();
}
} }
// Add the new range in its sorted location. // Add the new range in its sorted location.
style_ranges->insert(i, style_range); style_ranges->insert(i, style_range);
...@@ -189,8 +188,8 @@ void RenderText::MoveCursorRight(BreakType break_type, bool select) { ...@@ -189,8 +188,8 @@ void RenderText::MoveCursorRight(BreakType break_type, bool select) {
MoveCursorTo(position); MoveCursorTo(position);
} }
bool RenderText::MoveCursorTo(const SelectionModel& model) { bool RenderText::MoveCursorTo(const SelectionModel& selection_model) {
SelectionModel sel(model); SelectionModel sel(selection_model);
size_t text_length = text().length(); size_t text_length = text().length();
// Enforce valid selection model components. // Enforce valid selection model components.
if (sel.selection_start() > text_length) if (sel.selection_start() > text_length)
...@@ -369,7 +368,7 @@ SelectionModel RenderText::FindCursorPosition(const Point& point) { ...@@ -369,7 +368,7 @@ SelectionModel RenderText::FindCursorPosition(const Point& point) {
// binary searching the cursor position. // binary searching the cursor position.
// TODO(oshima): use the center of character instead of edge. // TODO(oshima): use the center of character instead of edge.
// Binary search may not work for language like Arabic. // Binary search may not work for language like Arabic.
while (std::abs(right_pos - left_pos) > 1) { while (std::abs(static_cast<long>(right_pos - left_pos)) > 1) {
int pivot_pos = left_pos + (right_pos - left_pos) / 2; int pivot_pos = left_pos + (right_pos - left_pos) / 2;
int pivot = font.GetStringWidth(text().substr(0, pivot_pos)); int pivot = font.GetStringWidth(text().substr(0, pivot_pos));
if (pivot < x) { if (pivot < x) {
...@@ -431,7 +430,8 @@ SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current, ...@@ -431,7 +430,8 @@ SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
BreakType break_type) { BreakType break_type) {
if (break_type == LINE_BREAK) if (break_type == LINE_BREAK)
return LeftEndSelectionModel(); return LeftEndSelectionModel();
size_t pos = std::max<int>(current.selection_end() - 1, 0); size_t pos = std::max(static_cast<long>(current.selection_end() - 1),
static_cast<long>(0));
if (break_type == CHARACTER_BREAK) if (break_type == CHARACTER_BREAK)
return SelectionModel(pos, pos, SelectionModel::LEADING); return SelectionModel(pos, pos, SelectionModel::LEADING);
...@@ -505,7 +505,8 @@ void RenderText::SetSelectionModel(const SelectionModel& model) { ...@@ -505,7 +505,8 @@ void RenderText::SetSelectionModel(const SelectionModel& model) {
selection_model_.set_selection_start(model.selection_start()); selection_model_.set_selection_start(model.selection_start());
DCHECK_LE(model.selection_end(), text().length()); DCHECK_LE(model.selection_end(), text().length());
selection_model_.set_selection_end(model.selection_end()); selection_model_.set_selection_end(model.selection_end());
DCHECK_LT(model.caret_pos(), std::max<size_t>(text().length(), 1)); DCHECK_LT(model.caret_pos(),
std::max(text().length(), static_cast<size_t>(1)));
selection_model_.set_caret_pos(model.caret_pos()); selection_model_.set_caret_pos(model.caret_pos());
selection_model_.set_caret_placement(model.caret_placement()); selection_model_.set_caret_placement(model.caret_placement());
......
...@@ -234,9 +234,6 @@ class UI_EXPORT RenderText { ...@@ -234,9 +234,6 @@ class UI_EXPORT RenderText {
virtual void DrawVisualText(Canvas* canvas) = 0; virtual void DrawVisualText(Canvas* canvas) = 0;
// Get the logical index of the grapheme preceding the argument |position|. // Get the logical index of the grapheme preceding the argument |position|.
// If |IsCursorablePosition(position)| is true, the result will be the start
// of the previous grapheme, if any. Otherwise, the result will be the start
// of the grapheme containing |position|.
size_t GetIndexOfPreviousGrapheme(size_t position); size_t GetIndexOfPreviousGrapheme(size_t position);
// Apply composition style (underline) to composition range and selection // Apply composition style (underline) to composition range and selection
...@@ -255,13 +252,8 @@ class UI_EXPORT RenderText { ...@@ -255,13 +252,8 @@ class UI_EXPORT RenderText {
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, GraphemePositions);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, SelectionModels);
// Return an index belonging to the |next| or previous logical grapheme. // Return an index belonging to the |next| or previous logical grapheme.
// If |next| is false and |IsCursorablePosition(index)| is true, the result
// will be the start of the previous grapheme, if any. Otherwise, the result
// will be the start of the grapheme containing |index|.
// The return value is bounded by 0 and the text length, inclusive. // The return value is bounded by 0 and the text length, inclusive.
virtual size_t IndexOfAdjacentGrapheme(size_t index, bool next) = 0; virtual size_t IndexOfAdjacentGrapheme(size_t index, bool next) = 0;
......
...@@ -284,8 +284,6 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) { ...@@ -284,8 +284,6 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
} }
size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) { size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) {
if (index > text().length())
return text().length();
EnsureLayout(); EnsureLayout();
return Utf16IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), next); return Utf16IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), next);
} }
......
...@@ -543,105 +543,6 @@ TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) { ...@@ -543,105 +543,6 @@ TEST_F(RenderTextTest, MoveCursorLeftRight_ComplexScript) {
} }
#endif #endif
TEST_F(RenderTextTest, GraphemePositions) {
// LTR 2-character grapheme, LTR abc, LTR 2-character grapheme.
const string16 kText1 = WideToUTF16(L"\x0915\x093f"L"abc"L"\x0915\x093f");
// LTR ab, LTR 2-character grapheme, LTR cd.
const string16 kText2 = WideToUTF16(L"ab"L"\x0915\x093f"L"cd");
struct {
string16 text;
size_t index;
size_t expected_previous;
size_t expected_next;
} cases[] = {
{ string16(), 0, 0, 0 },
{ string16(), 1, 0, 0 },
{ string16(), 50, 0, 0 },
{ kText1, 0, 0, 2 },
{ kText1, 1, 0, 2 },
{ kText1, 2, 0, 3 },
{ kText1, 3, 2, 4 },
{ kText1, 4, 3, 5 },
{ kText1, 5, 4, 7 },
{ kText1, 6, 5, 7 },
{ kText1, 7, 5, 7 },
{ kText1, 8, 7, 7 },
{ kText1, 50, 7, 7 },
{ kText2, 0, 0, 1 },
{ kText2, 1, 0, 2 },
{ kText2, 2, 1, 4 },
{ kText2, 3, 2, 4 },
{ kText2, 4, 2, 5 },
{ kText2, 5, 4, 6 },
{ kText2, 6, 5, 6 },
{ kText2, 7, 6, 6 },
{ kText2, 50, 6, 6 },
};
scoped_ptr<RenderText> render_text(RenderText::CreateRenderText());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
render_text->SetText(cases[i].text);
size_t next = render_text->GetIndexOfNextGrapheme(cases[i].index);
EXPECT_EQ(cases[i].expected_next, next);
EXPECT_TRUE(render_text->IsCursorablePosition(next));
size_t previous = render_text->GetIndexOfPreviousGrapheme(cases[i].index);
EXPECT_EQ(cases[i].expected_previous, previous);
EXPECT_TRUE(render_text->IsCursorablePosition(previous));
}
}
TEST_F(RenderTextTest, SelectionModels) {
// Simple Latin text.
const string16 kLatin = WideToUTF16(L"abc");
// LTR 2-character grapheme.
const string16 kLTRGrapheme = WideToUTF16(L"\x0915\x093f");
// LTR 2-character grapheme, LTR a, LTR 2-character grapheme.
const string16 kHindiLatin = WideToUTF16(L"\x0915\x093f"L"a"L"\x0915\x093f");
// RTL 2-character grapheme.
const string16 kRTLGrapheme = WideToUTF16(L"\x05e0\x05b8");
// RTL 2-character grapheme, LTR a, RTL 2-character grapheme.
const string16 kHebrewLatin = WideToUTF16(L"\x05e0\x05b8"L"a"L"\x05e0\x05b8");
struct {
string16 text;
size_t expected_left_end_caret;
SelectionModel::CaretPlacement expected_left_end_placement;
size_t expected_right_end_caret;
SelectionModel::CaretPlacement expected_right_end_placement;
} cases[] = {
{ string16(), 0, SelectionModel::LEADING, 0, SelectionModel::LEADING },
{ kLatin, 0, SelectionModel::LEADING, 2, SelectionModel::TRAILING },
{ kLTRGrapheme, 0, SelectionModel::LEADING, 0, SelectionModel::TRAILING },
{ kHindiLatin, 0, SelectionModel::LEADING, 3, SelectionModel::TRAILING },
{ kRTLGrapheme, 0, SelectionModel::TRAILING, 0, SelectionModel::LEADING },
#if defined(OS_LINUX)
// On Linux, the whole string is displayed RTL, rather than individual runs.
{ kHebrewLatin, 3, SelectionModel::TRAILING, 0, SelectionModel::LEADING },
#else
{ kHebrewLatin, 0, SelectionModel::TRAILING, 3, SelectionModel::LEADING },
#endif
};
scoped_ptr<RenderText> render_text(RenderText::CreateRenderText());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
render_text->SetText(cases[i].text);
SelectionModel model = render_text->LeftEndSelectionModel();
EXPECT_EQ(cases[i].expected_left_end_caret, model.caret_pos());
EXPECT_TRUE(render_text->IsCursorablePosition(model.caret_pos()));
EXPECT_EQ(cases[i].expected_left_end_placement, model.caret_placement());
model = render_text->RightEndSelectionModel();
EXPECT_EQ(cases[i].expected_right_end_caret, model.caret_pos());
EXPECT_TRUE(render_text->IsCursorablePosition(model.caret_pos()));
EXPECT_EQ(cases[i].expected_right_end_placement, model.caret_placement());
}
}
TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) { TEST_F(RenderTextTest, MoveCursorLeftRightWithSelection) {
scoped_ptr<RenderText> render_text(RenderText::CreateRenderText()); scoped_ptr<RenderText> render_text(RenderText::CreateRenderText());
render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2")); render_text->SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2"));
......
...@@ -291,15 +291,10 @@ SelectionModel RenderTextWin::LeftEndSelectionModel() { ...@@ -291,15 +291,10 @@ SelectionModel RenderTextWin::LeftEndSelectionModel() {
EnsureLayout(); EnsureLayout();
size_t cursor = base::i18n::IsRTL() ? text().length() : 0; size_t cursor = base::i18n::IsRTL() ? text().length() : 0;
internal::TextRun* run = runs_[visual_to_logical_[0]]; internal::TextRun* run = runs_[visual_to_logical_[0]];
size_t caret; bool rtl = run->script_analysis.fRTL;
SelectionModel::CaretPlacement placement; size_t caret = rtl ? run->range.end() - 1 : run->range.start();
if (run->script_analysis.fRTL) { SelectionModel::CaretPlacement placement =
caret = IndexOfAdjacentGrapheme(run->range.end(), false); rtl ? SelectionModel::TRAILING : SelectionModel::LEADING;
placement = SelectionModel::TRAILING;
} else {
caret = run->range.start();
placement = SelectionModel::LEADING;
}
return SelectionModel(cursor, caret, placement); return SelectionModel(cursor, caret, placement);
} }
...@@ -310,15 +305,10 @@ SelectionModel RenderTextWin::RightEndSelectionModel() { ...@@ -310,15 +305,10 @@ SelectionModel RenderTextWin::RightEndSelectionModel() {
EnsureLayout(); EnsureLayout();
size_t cursor = base::i18n::IsRTL() ? 0 : text().length(); size_t cursor = base::i18n::IsRTL() ? 0 : text().length();
internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]]; internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]];
size_t caret; bool rtl = run->script_analysis.fRTL;
SelectionModel::CaretPlacement placement; size_t caret = rtl ? run->range.start() : run->range.end() - 1;
if (run->script_analysis.fRTL) { SelectionModel::CaretPlacement placement =
caret = run->range.start(); rtl ? SelectionModel::LEADING : SelectionModel::TRAILING;
placement = SelectionModel::LEADING;
} else {
caret = IndexOfAdjacentGrapheme(run->range.end(), false);
placement = SelectionModel::TRAILING;
}
return SelectionModel(cursor, caret, placement); return SelectionModel(cursor, caret, placement);
} }
...@@ -471,50 +461,22 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { ...@@ -471,50 +461,22 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) {
size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) { size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
EnsureLayout(); EnsureLayout();
if (text().empty())
return 0;
if (index >= text().length()) {
if (next || index > text().length()) {
return text().length();
} else {
// The requested |index| is at the end of the text. Use the index of the
// last character to find the grapheme.
index = text().length() - 1;
if (IsCursorablePosition(index))
return index;
}
}
size_t run_index = GetRunContainingPosition(index); size_t run_index = GetRunContainingPosition(index);
DCHECK(run_index < runs_.size()); internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL;
internal::TextRun* run = runs_[run_index]; int start = run ? run->range.start() : 0;
size_t start = run->range.start(); int length = run ? run->range.length() : text().length();
size_t ch = index - start; int ch = index - start;
WORD cluster = run ? run->logical_clusters[ch] : 0;
if (!next) { if (!next) {
// If |ch| is the start of the run, use the preceding run, if any.
if (ch == 0) {
if (run_index == 0)
return 0;
run = runs_[run_index - 1];
start = run->range.start();
ch = run->range.length();
}
// Loop to find the start of the grapheme.
WORD cluster = run->logical_clusters[ch - 1];
do { do {
ch--; ch--;
} while (ch > 0 && run->logical_clusters[ch - 1] == cluster); } while (ch >= 0 && run && run->logical_clusters[ch] == cluster);
} else { } else {
WORD cluster = run->logical_clusters[ch]; while (ch < length && run && run->logical_clusters[ch] == cluster)
while (ch < run->range.length() && run->logical_clusters[ch] == cluster)
ch++; ch++;
} }
return std::max(std::min(ch, length) + start, 0);
return start + ch;
} }
void RenderTextWin::ItemizeLogicalText() { void RenderTextWin::ItemizeLogicalText() {
...@@ -583,7 +545,6 @@ void RenderTextWin::LayoutVisualText() { ...@@ -583,7 +545,6 @@ void RenderTextWin::LayoutVisualText() {
internal::TextRun* run = *run_iter; internal::TextRun* run = *run_iter;
size_t run_length = run->range.length(); size_t run_length = run->range.length();
const wchar_t* run_text = &(text()[run->range.start()]); const wchar_t* run_text = &(text()[run->range.start()]);
bool tried_fallback = false;
// Select the font desired for glyph generation. // Select the font desired for glyph generation.
SelectObject(hdc, run->font.GetNativeFont()); SelectObject(hdc, run->font.GetNativeFont());
...@@ -608,21 +569,12 @@ void RenderTextWin::LayoutVisualText() { ...@@ -608,21 +569,12 @@ void RenderTextWin::LayoutVisualText() {
if (hr == E_OUTOFMEMORY) { if (hr == E_OUTOFMEMORY) {
max_glyphs *= 2; max_glyphs *= 2;
} else if (hr == USP_E_SCRIPT_NOT_IN_FONT) { } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
// Only try font fallback if it hasn't yet been attempted for this run. // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can crash
if (tried_fallback) { // on certain surrogate pairs with SCRIPT_UNDEFINED.
// TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
// crash on certain surrogate pairs with SCRIPT_UNDEFINED. // And http://maxradi.us/documents/uniscribe/
// See https://bugzilla.mozilla.org/show_bug.cgi?id=341500 if (run->script_analysis.eScript == SCRIPT_UNDEFINED)
// And http://maxradi.us/documents/uniscribe/ break;
run->script_analysis.eScript = SCRIPT_UNDEFINED;
// Reset |hr| to 0 to not trigger the DCHECK() below when a font is
// not found that can display the text. This is expected behavior
// under Windows XP without additional language packs installed and
// may also happen on newer versions when trying to display text in
// an obscure script that the system doesn't have the right font for.
hr = 0;
break;
}
// The run's font doesn't contain the required glyphs, use an alternate. // The run's font doesn't contain the required glyphs, use an alternate.
if (ChooseFallbackFont(hdc, run->font, run_text, run_length, if (ChooseFallbackFont(hdc, run->font, run_text, run_length,
...@@ -631,7 +583,7 @@ void RenderTextWin::LayoutVisualText() { ...@@ -631,7 +583,7 @@ void RenderTextWin::LayoutVisualText() {
SelectObject(hdc, run->font.GetNativeFont()); SelectObject(hdc, run->font.GetNativeFont());
} }
tried_fallback = true; run->script_analysis.eScript = SCRIPT_UNDEFINED;
} else { } else {
break; break;
} }
......
...@@ -20,10 +20,6 @@ ...@@ -20,10 +20,6 @@
#include "ui/views/test/views_test_base.h" #include "ui/views/test/views_test_base.h"
#include "ui/views/views_delegate.h" #include "ui/views/views_delegate.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
namespace { namespace {
struct WordAndCursor { struct WordAndCursor {
...@@ -141,15 +137,7 @@ TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) { ...@@ -141,15 +137,7 @@ TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) {
} }
TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
// TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
// font support for some scripts - http://crbug.com/106450
bool on_windows_xp = false;
#if defined(OS_WIN)
on_windows_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
#endif
TextfieldViewsModel model(NULL); TextfieldViewsModel model(NULL);
// Append two Hindi strings. // Append two Hindi strings.
model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915")); model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"), EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"),
...@@ -160,31 +148,32 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { ...@@ -160,31 +148,32 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
model.GetText()); model.GetText());
// Check it is not able to place cursor in middle of a grapheme. // Check it is not able to place cursor in middle of a grapheme.
// TODO(xji): temporarily disable in platform Win since the complex script
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
model.MoveCursorTo(gfx::SelectionModel(1U)); model.MoveCursorTo(gfx::SelectionModel(1U));
EXPECT_EQ(0U, model.GetCursorPosition()); EXPECT_EQ(0U, model.GetCursorPosition());
#endif
model.MoveCursorTo(gfx::SelectionModel(2U));
EXPECT_EQ(2U, model.GetCursorPosition());
model.InsertChar('a');
EXPECT_EQ(WideToUTF16(
L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
model.GetText());
// TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete // ReplaceChar will replace the whole grapheme.
// font support for some scripts - http://crbug.com/106450 model.ReplaceChar('b');
if (!on_windows_xp) { // TODO(xji): temporarily disable in platform Win since the complex script
model.MoveCursorTo(gfx::SelectionModel(2U)); // characters turned into empty square due to font regression. So, not able
EXPECT_EQ(2U, model.GetCursorPosition()); // to test 2 characters belong to the same grapheme.
model.InsertChar('a');
EXPECT_EQ(WideToUTF16(
L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
model.GetText());
// ReplaceChar will replace the whole grapheme.
model.ReplaceChar('b');
// TODO(xji): temporarily disable in platform Win since the complex script
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX) #if defined(OS_LINUX)
EXPECT_EQ(WideToUTF16( EXPECT_EQ(WideToUTF16(
L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"), L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
model.GetText()); model.GetText());
#endif #endif
EXPECT_EQ(4U, model.GetCursorPosition()); EXPECT_EQ(4U, model.GetCursorPosition());
}
// Delete should delete the whole grapheme. // Delete should delete the whole grapheme.
model.MoveCursorTo(gfx::SelectionModel(0U)); model.MoveCursorTo(gfx::SelectionModel(0U));
...@@ -196,7 +185,6 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { ...@@ -196,7 +185,6 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"), EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
model.GetText()); model.GetText());
model.MoveCursorTo(gfx::SelectionModel(model.GetText().length())); model.MoveCursorTo(gfx::SelectionModel(model.GetText().length()));
EXPECT_EQ(model.GetText().length(), model.GetCursorPosition());
EXPECT_TRUE(model.Backspace()); EXPECT_TRUE(model.Backspace());
EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"), EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"),
model.GetText()); model.GetText());
...@@ -207,25 +195,30 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { ...@@ -207,25 +195,30 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
model.MoveCursorTo(gfx::SelectionModel(0)); model.MoveCursorTo(gfx::SelectionModel(0));
EXPECT_EQ(0U, model.GetCursorPosition()); EXPECT_EQ(0U, model.GetCursorPosition());
// TODO(xji): temporarily disable in platform Win since the complex script
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
model.MoveCursorTo(gfx::SelectionModel(1)); model.MoveCursorTo(gfx::SelectionModel(1));
EXPECT_EQ(0U, model.GetCursorPosition()); EXPECT_EQ(0U, model.GetCursorPosition());
#endif
// TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
// font support for some scripts - http://crbug.com/106450
if (!on_windows_xp) {
model.MoveCursorTo(gfx::SelectionModel(3));
EXPECT_EQ(3U, model.GetCursorPosition());
}
// TODO(asvitkine): Temporarily disable the following check on Windows. It
// seems Windows treats "\x0D38\x0D4D\x0D15" as a single grapheme.
#if !defined(OS_WIN)
model.MoveCursorTo(gfx::SelectionModel(2)); model.MoveCursorTo(gfx::SelectionModel(2));
EXPECT_EQ(2U, model.GetCursorPosition()); EXPECT_EQ(2U, model.GetCursorPosition());
model.MoveCursorTo(gfx::SelectionModel(3));
EXPECT_EQ(3U, model.GetCursorPosition());
model.MoveCursorTo(gfx::SelectionModel(2));
EXPECT_TRUE(model.Backspace()); EXPECT_TRUE(model.Backspace());
EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText()); EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText());
#endif
// Test Delete/Backspace on Hebrew with non-spacing marks.
// TODO(xji): temporarily disable in platform Win since the complex script
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9")); model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
model.MoveCursorTo(gfx::SelectionModel(0)); model.MoveCursorTo(gfx::SelectionModel(0));
EXPECT_TRUE(model.Delete()); EXPECT_TRUE(model.Delete());
...@@ -233,6 +226,7 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { ...@@ -233,6 +226,7 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
EXPECT_TRUE(model.Delete()); EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete()); EXPECT_TRUE(model.Delete());
EXPECT_EQ(WideToUTF16(L""), model.GetText()); EXPECT_EQ(WideToUTF16(L""), model.GetText());
#endif
// The first 2 characters are not strong directionality characters. // The first 2 characters are not strong directionality characters.
model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC")); model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
...@@ -567,7 +561,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_Clipboard) { ...@@ -567,7 +561,7 @@ TEST_F(TextfieldViewsModelTest, MAYBE_Clipboard) {
EXPECT_EQ(29U, model.GetCursorPosition()); EXPECT_EQ(29U, model.GetCursorPosition());
} }
static void SelectWordTestVerifier(const TextfieldViewsModel& model, void SelectWordTestVerifier(TextfieldViewsModel &model,
const string16 &expected_selected_string, size_t expected_cursor_pos) { const string16 &expected_selected_string, size_t expected_cursor_pos) {
EXPECT_EQ(expected_selected_string, model.GetSelectedText()); EXPECT_EQ(expected_selected_string, model.GetSelectedText());
EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition()); EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment