diff options
author | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 00:37:09 +0000 |
---|---|---|
committer | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 00:37:09 +0000 |
commit | 0a12d5fdc9b861f48e0d431fa9f1887bf84246b1 (patch) | |
tree | 68aa74232007f5a106512de8a797d97a07e3a867 | |
parent | 51dbd1c879a48c7a28deb9f6e83e1a2d7ee78cee (diff) | |
download | chromium_src-0a12d5fdc9b861f48e0d431fa9f1887bf84246b1.zip chromium_src-0a12d5fdc9b861f48e0d431fa9f1887bf84246b1.tar.gz chromium_src-0a12d5fdc9b861f48e0d431fa9f1887bf84246b1.tar.bz2 |
Rewrite RenderText::IndexOfAdjacentGrapheme() in terms of IsCursorablePosition().
This moves the implementation of IndexOfAdjacentGrapheme() entirely into the base class, removing the need for platform-specific implementations.
This rewrite exposed a couple of problems in RenderTextLinux::IsCursorablePosition() that caused some tests to fail. The fixes are also included.
Also includes additional test coverage for UTF16 surrogate pairs, which was only caught by a Linux-specific password censorship test.
BUG=125664
TEST=Existing unit tests.
Review URL: https://chromiumcodereview.appspot.com/10389148
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137320 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/gfx/render_text.cc | 24 | ||||
-rw-r--r-- | ui/gfx/render_text.h | 4 | ||||
-rw-r--r-- | ui/gfx/render_text_linux.cc | 28 | ||||
-rw-r--r-- | ui/gfx/render_text_linux.h | 3 | ||||
-rw-r--r-- | ui/gfx/render_text_unittest.cc | 16 | ||||
-rw-r--r-- | ui/gfx/render_text_win.cc | 51 | ||||
-rw-r--r-- | ui/gfx/render_text_win.h | 3 |
7 files changed, 46 insertions, 83 deletions
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 79ded6f..46b1d00 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc @@ -653,6 +653,30 @@ const Rect& RenderText::GetUpdatedCursorBounds() { return cursor_bounds_; } +size_t RenderText::IndexOfAdjacentGrapheme(size_t index, + LogicalCursorDirection direction) { + if (index > text().length()) + return text().length(); + + EnsureLayout(); + + if (direction == CURSOR_FORWARD) { + while (index < text().length()) { + index++; + if (IsCursorablePosition(index)) + return index; + } + return text().length(); + } + + while (index > 0) { + index--; + if (IsCursorablePosition(index)) + return index; + } + return 0; +} + SelectionModel RenderText::GetSelectionModelForSelectionStart() { const ui::Range& sel = selection(); if (sel.is_empty()) diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h index 4398366..f50c1d1 100644 --- a/ui/gfx/render_text.h +++ b/ui/gfx/render_text.h @@ -269,8 +269,8 @@ class UI_EXPORT RenderText { // range 0 to text().length() inclusive (the input is clamped if it is out of // that range). Always moves by at least one character index unless the // supplied index is already at the boundary of the string. - virtual size_t IndexOfAdjacentGrapheme(size_t index, - LogicalCursorDirection direction) = 0; + size_t IndexOfAdjacentGrapheme(size_t index, + LogicalCursorDirection direction); // Return a SelectionModel with the cursor at the current selection's start. // The returned value represents a cursor/caret position without a selection. diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc index d24f8be..f22342e 100644 --- a/ui/gfx/render_text_linux.cc +++ b/ui/gfx/render_text_linux.cc @@ -138,30 +138,6 @@ SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) { (trailing > 0) ? CURSOR_BACKWARD : CURSOR_FORWARD); } -size_t RenderTextLinux::IndexOfAdjacentGrapheme( - size_t index, - LogicalCursorDirection direction) { - if (index > text().length()) - return text().length(); - EnsureLayout(); - ptrdiff_t char_offset = ui::UTF16IndexToOffset(text(), 0, index); - if (direction == CURSOR_BACKWARD) { - if (char_offset > 0) { - do { - --char_offset; - } while (char_offset > 0 && !log_attrs_[char_offset].is_cursor_position); - } - } else { // direction == CURSOR_FORWARD - if (char_offset < num_log_attrs_ - 1) { - do { - ++char_offset; - } while (char_offset < num_log_attrs_ - 1 && - !log_attrs_[char_offset].is_cursor_position); - } - } - return ui::UTF16OffsetToIndex(text(), 0, char_offset); -} - std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() { EnsureLayout(); @@ -281,6 +257,10 @@ std::vector<Rect> RenderTextLinux::GetSubstringBounds(ui::Range range) { bool RenderTextLinux::IsCursorablePosition(size_t position) { if (position == 0 && text().empty()) return true; + if (position >= text().length()) + return position == text().length(); + if (!ui::IsValidCodePointIndex(text(), position)) + return false; EnsureLayout(); ptrdiff_t offset = ui::UTF16IndexToOffset(text(), 0, position); diff --git a/ui/gfx/render_text_linux.h b/ui/gfx/render_text_linux.h index cd3bf9a..4bc665c 100644 --- a/ui/gfx/render_text_linux.h +++ b/ui/gfx/render_text_linux.h @@ -23,9 +23,6 @@ class RenderTextLinux : public RenderText { virtual base::i18n::TextDirection GetTextDirection() OVERRIDE; virtual Size GetStringSize() OVERRIDE; virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE; - virtual size_t IndexOfAdjacentGrapheme( - size_t index, - LogicalCursorDirection direction) OVERRIDE; virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE; protected: diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index f0802410..bc79dc7 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc @@ -617,6 +617,13 @@ TEST_F(RenderTextTest, GraphemePositions) { // LTR ab, LTR 2-character grapheme, LTR cd. const string16 kText2 = WideToUTF16(L"ab"L"\x0915\x093f"L"cd"); + // The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as + // two characters forming the surrogate pair 0x0001D11E. + const std::string kSurrogate = "\xF0\x9D\x84\x9E"; + + // LTR ab, UTF16 surrogate pair, LTR cd. + const string16 kText3 = UTF8ToUTF16("ab" + kSurrogate + "cd"); + struct { string16 text; size_t index; @@ -645,6 +652,15 @@ TEST_F(RenderTextTest, GraphemePositions) { { kText2, 6, 5, 6 }, { kText2, 7, 6, 6 }, { kText2, 50, 6, 6 }, + { kText3, 0, 0, 1 }, + { kText3, 1, 0, 2 }, + { kText3, 2, 1, 4 }, + { kText3, 3, 2, 4 }, + { kText3, 4, 2, 5 }, + { kText3, 5, 4, 6 }, + { kText3, 6, 5, 6 }, + { kText3, 7, 6, 6 }, + { kText3, 50, 6, 6 }, }; // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc index b5cfec3..6705cb6 100644 --- a/ui/gfx/render_text_win.cc +++ b/ui/gfx/render_text_win.cc @@ -251,57 +251,6 @@ SelectionModel RenderTextWin::FindCursorPosition(const Point& point) { return SelectionModel(cursor, trailing ? CURSOR_BACKWARD : CURSOR_FORWARD); } -size_t RenderTextWin::IndexOfAdjacentGrapheme( - size_t index, - LogicalCursorDirection direction) { - EnsureLayout(); - - if (text().empty()) - return 0; - - if (index >= text().length()) { - if (direction == CURSOR_FORWARD || 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 = - GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); - DCHECK(run_index < runs_.size()); - internal::TextRun* run = runs_[run_index]; - size_t start = run->range.start(); - size_t ch = index - start; - - if (direction == CURSOR_BACKWARD) { - // 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 { - ch--; - } while (ch > 0 && run->logical_clusters[ch - 1] == cluster); - } else { // direction == CURSOR_FORWARD - WORD cluster = run->logical_clusters[ch]; - while (ch < run->range.length() && run->logical_clusters[ch] == cluster) - ch++; - } - - return start + ch; -} - std::vector<RenderText::FontSpan> RenderTextWin::GetFontSpansForTesting() { EnsureLayout(); diff --git a/ui/gfx/render_text_win.h b/ui/gfx/render_text_win.h index 9a5ff65..02fc0a0 100644 --- a/ui/gfx/render_text_win.h +++ b/ui/gfx/render_text_win.h @@ -69,9 +69,6 @@ class RenderTextWin : public RenderText { virtual base::i18n::TextDirection GetTextDirection() OVERRIDE; virtual Size GetStringSize() OVERRIDE; virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE; - virtual size_t IndexOfAdjacentGrapheme( - size_t index, - LogicalCursorDirection direction) OVERRIDE; virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE; protected: |