summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-16 00:37:09 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-16 00:37:09 +0000
commit0a12d5fdc9b861f48e0d431fa9f1887bf84246b1 (patch)
tree68aa74232007f5a106512de8a797d97a07e3a867
parent51dbd1c879a48c7a28deb9f6e83e1a2d7ee78cee (diff)
downloadchromium_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.cc24
-rw-r--r--ui/gfx/render_text.h4
-rw-r--r--ui/gfx/render_text_linux.cc28
-rw-r--r--ui/gfx/render_text_linux.h3
-rw-r--r--ui/gfx/render_text_unittest.cc16
-rw-r--r--ui/gfx/render_text_win.cc51
-rw-r--r--ui/gfx/render_text_win.h3
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: