<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197982] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197982">197982</a></dd>
<dt>Author</dt> <dd>n_wang@apple.com</dd>
<dt>Date</dt> <dd>2016-03-10 18:37:46 -0800 (Thu, 10 Mar 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>AX: Implement bounds/position and index related text marker functions using TextIterator
https://bugs.webkit.org/show_bug.cgi?id=154976
Reviewed by Chris Fleizach.
Source/WebCore:
Implemented position and index related text marker calls with TextIterator. Also fixed some
VoiceOver navigation issues.
Test: accessibility/mac/text-marker-for-index.html
* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::traverseToOffsetInRange):
(WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
(WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
(WebCore::AXObjectCache::shouldSkipBoundary):
(WebCore::AXObjectCache::textMarkerDataForNextCharacterOffset):
(WebCore::AXObjectCache::startCharacterOffsetOfWord):
(WebCore::AXObjectCache::nextBoundary):
(WebCore::AXObjectCache::previousBoundary):
(WebCore::AXObjectCache::previousSentenceStartCharacterOffset):
(WebCore::AXObjectCache::localCaretRectForCharacterOffset):
(WebCore::AXObjectCache::absoluteCaretBoundsForCharacterOffset):
(WebCore::AXObjectCache::characterOffsetForPoint):
(WebCore::AXObjectCache::characterOffsetForBounds):
(WebCore::AXObjectCache::endCharacterOffsetOfLine):
(WebCore::AXObjectCache::startCharacterOffsetOfLine):
(WebCore::AXObjectCache::characterOffsetForIndex):
(WebCore::AXObjectCache::indexForCharacterOffset):
(WebCore::AXObjectCache::rootAXEditableElement):
* accessibility/AXObjectCache.h:
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::visiblePositionRangeForRange):
(WebCore::AccessibilityObject::rangeForPlainTextRange):
(WebCore::AccessibilityObject::lineRangeForPosition):
* accessibility/AccessibilityObject.h:
(WebCore::AccessibilityObject::boundsForVisiblePositionRange):
(WebCore::AccessibilityObject::boundsForRange):
(WebCore::AccessibilityObject::setSelectedVisiblePositionRange):
(WebCore::AccessibilityObject::doAXStringForRange):
(WebCore::AccessibilityObject::doAXBoundsForRange):
(WebCore::AccessibilityObject::doAXBoundsForRangeUsingCharacterOffset):
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::nodeIsTextControl):
(WebCore::AccessibilityRenderObject::boundsForRects):
(WebCore::AccessibilityRenderObject::boundsForVisiblePositionRange):
(WebCore::AccessibilityRenderObject::boundsForRange):
(WebCore::AccessibilityRenderObject::setSelectedVisiblePositionRange):
(WebCore::AccessibilityRenderObject::doAXBoundsForRange):
(WebCore::AccessibilityRenderObject::doAXBoundsForRangeUsingCharacterOffset):
(WebCore::AccessibilityRenderObject::accessibilityImageMapHitTest):
* accessibility/AccessibilityRenderObject.h:
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper positionForTextMarker:]):
(-[WebAccessibilityObjectWrapper textMarkerRange]):
(-[WebAccessibilityObjectWrapper textMarkerRangeForSelection]):
(-[WebAccessibilityObjectWrapper textMarkerForPosition:]):
(-[WebAccessibilityObjectWrapper _stringForRange:attributed:]):
(-[WebAccessibilityObjectWrapper frameForTextMarkers:]):
(-[WebAccessibilityObjectWrapper textMarkerForPoint:]):
(-[WebAccessibilityObjectWrapper nextMarkerForCharacterOffset:]):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper doAXAttributedStringForRange:]):
(-[WebAccessibilityObjectWrapper _convertToNSRange:]):
(-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
(-[WebAccessibilityObjectWrapper _textMarkerForIndex:]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
* editing/htmlediting.cpp:
(WebCore::localCaretRectInRendererForCaretPainting):
(WebCore::localCaretRectInRendererForRect):
* editing/htmlediting.h:
LayoutTests:
* accessibility/mac/text-marker-for-index-expected.txt: Added.
* accessibility/mac/text-marker-for-index.html: Added.
* accessibility/mac/text-marker-word-nav-expected.txt:
* accessibility/mac/text-marker-word-nav.html:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerwordnavexpectedtxt">trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerwordnavhtml">trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCachecpp">trunk/Source/WebCore/accessibility/AXObjectCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAXObjectCacheh">trunk/Source/WebCore/accessibility/AXObjectCache.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityObject.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityObjecth">trunk/Source/WebCore/accessibility/AccessibilityObject.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityRenderObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityRenderObjecth">trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityiosWebAccessibilityObjectWrapperIOSmm">trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm</a></li>
<li><a href="#trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm">trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm</a></li>
<li><a href="#trunkSourceWebCoreeditinghtmleditingcpp">trunk/Source/WebCore/editing/htmlediting.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditinghtmleditingh">trunk/Source/WebCore/editing/htmlediting.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerforindexexpectedtxt">trunk/LayoutTests/accessibility/mac/text-marker-for-index-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerforindexhtml">trunk/LayoutTests/accessibility/mac/text-marker-for-index.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/LayoutTests/ChangeLog        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-03-10 Nan Wang <n_wang@apple.com>
+
+ AX: Implement bounds/position and index related text marker functions using TextIterator
+ https://bugs.webkit.org/show_bug.cgi?id=154976
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/mac/text-marker-for-index-expected.txt: Added.
+ * accessibility/mac/text-marker-for-index.html: Added.
+ * accessibility/mac/text-marker-word-nav-expected.txt:
+ * accessibility/mac/text-marker-word-nav.html:
+
</ins><span class="cx"> 2016-03-10 Myles C. Maxfield <mmaxfield@apple.com>
</span><span class="cx">
</span><span class="cx"> [Cocoa] Test gardening after r197933
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerforindexexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-for-index-expected.txt (0 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-for-index-expected.txt         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-for-index-expected.txt        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+text
+
+text
+audio file.
+This verifies that textMarkerForIndex and indexForTextMarker are working correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Original marker string: x
+Index is: 3
+New marker string: x
+
+Original marker string: 'line break'
+Index is: 6
+New marker string: 'line break'
+
+Original marker string: f
+Index is: 18
+New marker string: f
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerforindexhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-for-index.html (0 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-for-index.html         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-for-index.html        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<script src="../../resources/js-test-pre.js"></script>
+<body id="body" tabindex="0">
+
+<div tabindex="0" id="text1">text</div>
+<br>
+text
+
+<div id="text2">
+audio <audio controls><source src="test.mp3" type="audio/mpeg"></audio>file.
+</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This verifies that textMarkerForIndex and indexForTextMarker are working correctly.");
+
+ if (window.accessibilityController) {
+ var text = accessibilityController.accessibleElementById("text1");
+ // Get the actual text node.
+ text = text.childAtIndex(0);
+
+ var previous, current;
+ var textMarkerRange = text.textMarkerRangeForElement(text);
+ var startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ var result = forward(3, previous, startMarker, text);
+ previous = result.previous;
+ current = result.current;
+ verifyMarkerIndex(previous, current, text);
+
+ // BR
+ result = forward(2, previous, current, text);
+ previous = result.previous;
+ current = result.current;
+ verifyMarkerIndex(previous, current, text);
+
+ // Attachment
+ text = accessibilityController.accessibleElementById("text2");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ result = forward(8, previous, startMarker, text);
+ previous = result.previous;
+ current = result.current;
+ verifyMarkerIndex(previous, current, text);
+ }
+
+
+ function forward(count, previousMarker, currentMarker, obj) {
+ for (var i = 0; i < count; i++) {
+ previousMarker = currentMarker;
+ currentMarker = obj.nextTextMarker(currentMarker);
+ }
+ return {
+ previous: previousMarker,
+ current: currentMarker
+ };
+ }
+
+ function replaceLinebreakInString(str) {
+ var newline = '\n';
+ str = str.replace(newline, "'line break'");
+ return str;
+ }
+
+ function verifyMarkerIndex(previousMarker, textMarker, obj) {
+ var markerRange = obj.textMarkerRangeForMarkers(previousMarker, textMarker);
+ var originalString = replaceLinebreakInString(obj.stringForTextMarkerRange(markerRange));
+ debug("Original marker string: " + originalString);
+
+ var index = obj.indexForTextMarker(textMarker);
+ var newMarker = obj.textMarkerForIndex(index);
+ markerRange = obj.textMarkerRangeForMarkers(previousMarker, newMarker);
+ var newString = replaceLinebreakInString(obj.stringForTextMarkerRange(markerRange));
+ debug("Index is: " + index + "\nNew marker string: " + newString + "\n");
+ }
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+
+</body>
+</html>
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerwordnavexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/LayoutTests/accessibility/mac/text-marker-word-nav-expected.txt        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -9,6 +9,8 @@
</span><span class="cx"> some
</span><span class="cx"> text
</span><span class="cx"> test audio file
</span><ins>+Edit text
+
</ins><span class="cx"> This tests that word navigation is working correctly.
</span><span class="cx">
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span><span class="lines">@@ -59,6 +61,11 @@
</span><span class="cx"> Right word is: can't
</span><span class="cx"> Pre word start to next word end: can't
</span><span class="cx">
</span><ins>+Current character is:
+Left word is: 巧克力
+Right word is: 巧克力
+Pre word start to next word end: select'line break'巧克力
+
</ins><span class="cx"> Current character is: 克
</span><span class="cx"> Left word is: 巧克力
</span><span class="cx"> Right word is: 巧克力
</span><span class="lines">@@ -119,6 +126,11 @@
</span><span class="cx"> Right word is: file
</span><span class="cx"> Pre word start to next word end: file
</span><span class="cx">
</span><ins>+Current character is: t
+Left word is: Edit
+Right word is:
+Pre word start to next word end: Edit text
+
</ins><span class="cx"> Test going forward.
</span><span class="cx"> End word: file
</span><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerwordnavhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/LayoutTests/accessibility/mac/text-marker-word-nav.html        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -39,6 +39,11 @@
</span><span class="cx"> test audio <audio controls><source src="test.mp3" type="audio/mpeg"></audio>file
</span><span class="cx"> </div>
</span><span class="cx">
</span><ins>+<p id="text8">
+<strong>Edit</strong>
+text
+</p>
+
</ins><span class="cx"> <p id="description"></p>
</span><span class="cx"> <div id="console"></div>
</span><span class="cx">
</span><span class="lines">@@ -64,13 +69,13 @@
</span><span class="cx"> // At "T" in "Thisis", should return the word as "Thisislongword".
</span><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 2, text);
</span><span class="cx"> // At " " before "I", the word should be "I'll".
</span><del>- currentMarker = advanceAndVerify(currentMarker, 15, text);
</del><ins>+ currentMarker = advanceAndVerify(currentMarker, 14, text);
</ins><span class="cx"> // At " " before "try", the word should excludes "."
</span><del>- currentMarker = advanceAndVerify(currentMarker, 6, text);
</del><ins>+ currentMarker = advanceAndVerify(currentMarker, 5, text);
</ins><span class="cx">
</span><span class="cx"> // Check the case with contenteditable
</span><span class="cx"> // At "e" in "editable", the word should NOT include "Content" before it.
</span><del>- currentMarker = advanceAndVerify(currentMarker, 19, text);
</del><ins>+ currentMarker = advanceAndVerify(currentMarker, 18, text);
</ins><span class="cx">
</span><span class="cx"> // Check the case with replaced node, the replaced node should be considered a word.
</span><span class="cx"> var text2 = accessibilityController.accessibleElementById("text2");
</span><span class="lines">@@ -89,6 +94,8 @@
</span><span class="cx"> var text4 = accessibilityController.accessibleElementById("text4");
</span><span class="cx"> textMarkerRange = text4.textMarkerRangeForElement(text4);
</span><span class="cx"> currentMarker = text4.startTextMarkerForTextMarkerRange(textMarkerRange);
</span><ins>+ // Make sure when we are at the beginning of line, it won't go to previous node.
+ currentMarker = advanceAndVerify(currentMarker, 0, text4);
</ins><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 2, text4);
</span><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 1, text4);
</span><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 1, text4);
</span><span class="lines">@@ -123,12 +130,18 @@
</span><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 1, text7);
</span><span class="cx"> currentMarker = advanceAndVerify(currentMarker, 1, text7);
</span><span class="cx">
</span><ins>+ // For node with text node children, we should treat the visual space as word boundary.
+ var text8 = accessibilityController.accessibleElementById("text8");
+ textMarkerRange = text8.textMarkerRangeForElement(text8);
+ currentMarker = text8.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(currentMarker, 4, text8);
+
</ins><span class="cx"> // Check the word marker runs from start to end, and backwards.
</span><span class="cx"> // Make sure it won't hang.
</span><span class="cx"> verifyDocument(text);
</span><span class="cx">
</span><span class="cx"> function advanceAndVerify(currentMarker, offset, obj) {
</span><del>- var previousMarker;
</del><ins>+ var previousMarker = currentMarker;
</ins><span class="cx"> for (var i = 0; i < offset; i++) {
</span><span class="cx"> previousMarker = currentMarker;
</span><span class="cx"> currentMarker = obj.nextTextMarker(previousMarker);
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/ChangeLog        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1,3 +1,76 @@
</span><ins>+2016-03-10 Nan Wang <n_wang@apple.com>
+
+ AX: Implement bounds/position and index related text marker functions using TextIterator
+ https://bugs.webkit.org/show_bug.cgi?id=154976
+
+ Reviewed by Chris Fleizach.
+
+ Implemented position and index related text marker calls with TextIterator. Also fixed some
+ VoiceOver navigation issues.
+
+ Test: accessibility/mac/text-marker-for-index.html
+
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::AXObjectCache::traverseToOffsetInRange):
+ (WebCore::AXObjectCache::startOrEndCharacterOffsetForRange):
+ (WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
+ (WebCore::AXObjectCache::shouldSkipBoundary):
+ (WebCore::AXObjectCache::textMarkerDataForNextCharacterOffset):
+ (WebCore::AXObjectCache::startCharacterOffsetOfWord):
+ (WebCore::AXObjectCache::nextBoundary):
+ (WebCore::AXObjectCache::previousBoundary):
+ (WebCore::AXObjectCache::previousSentenceStartCharacterOffset):
+ (WebCore::AXObjectCache::localCaretRectForCharacterOffset):
+ (WebCore::AXObjectCache::absoluteCaretBoundsForCharacterOffset):
+ (WebCore::AXObjectCache::characterOffsetForPoint):
+ (WebCore::AXObjectCache::characterOffsetForBounds):
+ (WebCore::AXObjectCache::endCharacterOffsetOfLine):
+ (WebCore::AXObjectCache::startCharacterOffsetOfLine):
+ (WebCore::AXObjectCache::characterOffsetForIndex):
+ (WebCore::AXObjectCache::indexForCharacterOffset):
+ (WebCore::AXObjectCache::rootAXEditableElement):
+ * accessibility/AXObjectCache.h:
+ * accessibility/AccessibilityObject.cpp:
+ (WebCore::AccessibilityObject::visiblePositionRangeForRange):
+ (WebCore::AccessibilityObject::rangeForPlainTextRange):
+ (WebCore::AccessibilityObject::lineRangeForPosition):
+ * accessibility/AccessibilityObject.h:
+ (WebCore::AccessibilityObject::boundsForVisiblePositionRange):
+ (WebCore::AccessibilityObject::boundsForRange):
+ (WebCore::AccessibilityObject::setSelectedVisiblePositionRange):
+ (WebCore::AccessibilityObject::doAXStringForRange):
+ (WebCore::AccessibilityObject::doAXBoundsForRange):
+ (WebCore::AccessibilityObject::doAXBoundsForRangeUsingCharacterOffset):
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::nodeIsTextControl):
+ (WebCore::AccessibilityRenderObject::boundsForRects):
+ (WebCore::AccessibilityRenderObject::boundsForVisiblePositionRange):
+ (WebCore::AccessibilityRenderObject::boundsForRange):
+ (WebCore::AccessibilityRenderObject::setSelectedVisiblePositionRange):
+ (WebCore::AccessibilityRenderObject::doAXBoundsForRange):
+ (WebCore::AccessibilityRenderObject::doAXBoundsForRangeUsingCharacterOffset):
+ (WebCore::AccessibilityRenderObject::accessibilityImageMapHitTest):
+ * accessibility/AccessibilityRenderObject.h:
+ * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+ (-[WebAccessibilityObjectWrapper positionForTextMarker:]):
+ (-[WebAccessibilityObjectWrapper textMarkerRange]):
+ (-[WebAccessibilityObjectWrapper textMarkerRangeForSelection]):
+ (-[WebAccessibilityObjectWrapper textMarkerForPosition:]):
+ (-[WebAccessibilityObjectWrapper _stringForRange:attributed:]):
+ (-[WebAccessibilityObjectWrapper frameForTextMarkers:]):
+ (-[WebAccessibilityObjectWrapper textMarkerForPoint:]):
+ (-[WebAccessibilityObjectWrapper nextMarkerForCharacterOffset:]):
+ * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+ (-[WebAccessibilityObjectWrapper doAXAttributedStringForRange:]):
+ (-[WebAccessibilityObjectWrapper _convertToNSRange:]):
+ (-[WebAccessibilityObjectWrapper _indexForTextMarker:]):
+ (-[WebAccessibilityObjectWrapper _textMarkerForIndex:]):
+ (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+ * editing/htmlediting.cpp:
+ (WebCore::localCaretRectInRendererForCaretPainting):
+ (WebCore::localCaretRectInRendererForRect):
+ * editing/htmlediting.h:
+
</ins><span class="cx"> 2016-03-10 Simon Fraser <simon.fraser@apple.com>
</span><span class="cx">
</span><span class="cx"> Font antialiasing (smoothing) changes when elements are rendered into compositing layers
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1506,8 +1506,9 @@
</span><span class="cx"> currentNode = childNode;
</span><span class="cx"> hasReplacedNodeOrBR = true;
</span><span class="cx"> } else if (currentNode != previousNode) {
</span><del>- // We should set the currentNode to previous one in case this is the last iteration.
- currentNode = previousNode;
</del><ins>+ // We should set the start offset and length for the current node in case this is the last iteration.
+ lastStartOffset = 1;
+ lastLength = 0;
</ins><span class="cx"> continue;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1695,6 +1696,10 @@
</span><span class="cx"> if (!range)
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><ins>+ // When getting the end CharacterOffset at node boundary, we don't want to collapse to the previous node.
+ if (!isStart && !range->endOffset())
+ return characterOffsetForNodeAndOffset(range->endContainer(), 0, TraverseOptionIncludeStart);
+
</ins><span class="cx"> // If it's end text marker, we want to go to the end of the range, and stay within the range.
</span><span class="cx"> bool stayWithinRange = !isStart;
</span><span class="cx">
</span><span class="lines">@@ -1775,12 +1780,35 @@
</span><span class="cx"> setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool AXObjectCache::shouldSkipBoundary(const CharacterOffset& previous, const CharacterOffset& next)
+{
+ // Match the behavior of VisiblePosition, we should skip the node boundary when there's no visual space or new line character.
+ if (previous.isNull() || next.isNull())
+ return false;
+
+ if (previous.node == next.node)
+ return false;
+
+ if (next.startIndex > 0 || next.offset > 0)
+ return false;
+
+ CharacterOffset newLine = startCharacterOffsetOfLine(next);
+ if (next.isEqual(newLine))
+ return false;
+
+ return true;
+}
+
</ins><span class="cx"> void AXObjectCache::textMarkerDataForNextCharacterOffset(TextMarkerData& textMarkerData, const CharacterOffset& characterOffset)
</span><span class="cx"> {
</span><span class="cx"> CharacterOffset next = characterOffset;
</span><ins>+ CharacterOffset previous = characterOffset;
</ins><span class="cx"> do {
</span><span class="cx"> next = nextCharacterOffset(next, false);
</span><ins>+ if (shouldSkipBoundary(previous, next))
+ next = nextCharacterOffset(next, false);
</ins><span class="cx"> textMarkerDataForCharacterOffset(textMarkerData, next);
</span><ins>+ previous = next;
</ins><span class="cx"> } while (textMarkerData.ignored);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1958,7 +1986,10 @@
</span><span class="cx"> if (c.isEqual(endOfParagraph))
</span><span class="cx"> return c;
</span><span class="cx">
</span><del>- c = nextCharacterOffset(characterOffset);
</del><ins>+ // We should consider the node boundary that splits words. Otherwise VoiceOver won't see it as space.
+ c = nextCharacterOffset(characterOffset, false);
+ if (shouldSkipBoundary(characterOffset, c))
+ c = nextCharacterOffset(c, false);
</ins><span class="cx"> if (c.isNull())
</span><span class="cx"> return characterOffset;
</span><span class="cx"> }
</span><span class="lines">@@ -2106,6 +2137,10 @@
</span><span class="cx"> if (it.atEnd() && next == string.size())
</span><span class="cx"> return end;
</span><span class="cx">
</span><ins>+ // We should consider the node boundary that splits words.
+ if (searchFunction == endWordBoundary && next - prefixLength == 1)
+ return nextCharacterOffset(characterOffset, false);
+
</ins><span class="cx"> // The endSentenceBoundary function will include a line break at the end of the sentence.
</span><span class="cx"> if (searchFunction == endSentenceBoundary && string[next - 1] == '\n')
</span><span class="cx"> next--;
</span><span class="lines">@@ -2160,7 +2195,7 @@
</span><span class="cx">
</span><span class="cx"> int characterCount = characterOffset.offset - (string.size() - suffixLength - next);
</span><span class="cx"> // We don't want to go to the previous node if the node is at the start of a new line.
</span><del>- if (characterCount < 0 && (characterOffsetNodeIsBR(characterOffset) || string[string.size() - 1] == '\n'))
</del><ins>+ if (characterCount < 0 && (characterOffsetNodeIsBR(characterOffset) || string[string.size() - suffixLength - 1] == '\n'))
</ins><span class="cx"> characterCount = 0;
</span><span class="cx"> return characterOffsetForNodeAndOffset(*characterOffset.node, characterCount, TraverseOptionIncludeStart);
</span><span class="cx"> }
</span><span class="lines">@@ -2283,6 +2318,133 @@
</span><span class="cx"> return startCharacterOffsetOfSentence(previous);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+LayoutRect AXObjectCache::localCaretRectForCharacterOffset(RenderObject*& renderer, const CharacterOffset& characterOffset)
+{
+ if (characterOffset.isNull()) {
+ renderer = nullptr;
+ return IntRect();
+ }
+
+ Node* node = characterOffset.node;
+
+ renderer = node->renderer();
+ if (!renderer)
+ return LayoutRect();
+
+ InlineBox* inlineBox = nullptr;
+ int caretOffset;
+ // Use a collapsed range to get the position.
+ RefPtr<Range> range = rangeForUnorderedCharacterOffsets(characterOffset, characterOffset);
+ Position startPosition = range->startPosition();
+ startPosition.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset);
+
+ if (inlineBox)
+ renderer = &inlineBox->renderer();
+
+ return renderer->localCaretRect(inlineBox, caretOffset);
+}
+
+IntRect AXObjectCache::absoluteCaretBoundsForCharacterOffset(const CharacterOffset& characterOffset)
+{
+ RenderBlock* caretPainter = nullptr;
+
+ // First compute a rect local to the renderer at the selection start.
+ RenderObject* renderer = nullptr;
+ LayoutRect localRect = localCaretRectForCharacterOffset(renderer, characterOffset);
+
+ localRect = localCaretRectInRendererForRect(localRect, characterOffset.node, renderer, caretPainter);
+ return absoluteBoundsForLocalCaretRect(caretPainter, localRect);
+}
+
+CharacterOffset AXObjectCache::characterOffsetForPoint(const IntPoint &point, AccessibilityObject* obj)
+{
+ if (!obj)
+ return CharacterOffset();
+
+ VisiblePosition vp = obj->visiblePositionForPoint(point);
+ RefPtr<Range> range = makeRange(vp, vp);
+ return startOrEndCharacterOffsetForRange(range, true);
+}
+
+CharacterOffset AXObjectCache::characterOffsetForPoint(const IntPoint &point)
+{
+ RefPtr<Range> caretRange = m_document.caretRangeFromPoint(LayoutPoint(point));
+ return startOrEndCharacterOffsetForRange(caretRange, true);
+}
+
+CharacterOffset AXObjectCache::characterOffsetForBounds(const IntRect& rect, bool first)
+{
+ if (rect.isEmpty())
+ return CharacterOffset();
+
+ IntPoint corner = first ? rect.minXMinYCorner() : rect.maxXMaxYCorner();
+ CharacterOffset characterOffset = characterOffsetForPoint(corner);
+
+ if (rect.contains(absoluteCaretBoundsForCharacterOffset(characterOffset).center()))
+ return characterOffset;
+
+ // If the initial position is located outside the bounds adjust it incrementally as needed.
+ CharacterOffset nextCharOffset = nextCharacterOffset(characterOffset, false);
+ CharacterOffset previousCharOffset = previousCharacterOffset(characterOffset, false);
+ while (!nextCharOffset.isNull() || !previousCharOffset.isNull()) {
+ if (rect.contains(absoluteCaretBoundsForCharacterOffset(nextCharOffset).center()))
+ return nextCharOffset;
+ if (rect.contains(absoluteCaretBoundsForCharacterOffset(previousCharOffset).center()))
+ return previousCharOffset;
+
+ nextCharOffset = nextCharacterOffset(nextCharOffset, false);
+ previousCharOffset = previousCharacterOffset(previousCharOffset, false);
+ }
+
+ return CharacterOffset();
+}
+
+// FIXME: Remove VisiblePosition code after implementing this using CharacterOffset.
+CharacterOffset AXObjectCache::endCharacterOffsetOfLine(const CharacterOffset& characterOffset)
+{
+ if (characterOffset.isNull())
+ return CharacterOffset();
+
+ VisiblePosition vp = visiblePositionFromCharacterOffset(characterOffset);
+ VisiblePosition endLine = endOfLine(vp);
+
+ return characterOffsetFromVisiblePosition(endLine);
+}
+
+CharacterOffset AXObjectCache::startCharacterOffsetOfLine(const CharacterOffset& characterOffset)
+{
+ if (characterOffset.isNull())
+ return CharacterOffset();
+
+ VisiblePosition vp = visiblePositionFromCharacterOffset(characterOffset);
+ VisiblePosition startLine = startOfLine(vp);
+
+ return characterOffsetFromVisiblePosition(startLine);
+}
+
+CharacterOffset AXObjectCache::characterOffsetForIndex(int index, const AccessibilityObject* obj)
+{
+ if (!obj)
+ return CharacterOffset();
+
+ // Since this would only work on rendered nodes, using VisiblePosition to create a collapsed
+ // range should be fine.
+ VisiblePosition vp = obj->visiblePositionForIndex(index);
+ RefPtr<Range> range = makeRange(vp, vp);
+
+ return startOrEndCharacterOffsetForRange(range, true);
+}
+
+int AXObjectCache::indexForCharacterOffset(const CharacterOffset& characterOffset, AccessibilityObject* obj)
+{
+ // Create a collapsed range so that we can get the VisiblePosition from it.
+ RefPtr<Range> range = rangeForUnorderedCharacterOffsets(characterOffset, characterOffset);
+ if (!range)
+ return 0;
+ VisiblePosition vp = range->startPosition();
+ return obj->indexForVisiblePosition(vp);
+}
+
</ins><span class="cx"> const Element* AXObjectCache::rootAXEditableElement(const Node* node)
</span><span class="cx"> {
</span><span class="cx"> const Element* result = node->rootEditableElement();
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -200,6 +200,7 @@
</span><span class="cx"> CharacterOffset nextCharacterOffset(const CharacterOffset&, bool ignoreNextNodeStart = true);
</span><span class="cx"> CharacterOffset previousCharacterOffset(const CharacterOffset&, bool ignorePreviousNodeEnd = true);
</span><span class="cx"> void startOrEndTextMarkerDataForRange(TextMarkerData&, RefPtr<Range>, bool);
</span><ins>+ CharacterOffset startOrEndCharacterOffsetForRange(RefPtr<Range>, bool);
</ins><span class="cx"> AccessibilityObject* accessibilityObjectForTextMarkerData(TextMarkerData&);
</span><span class="cx"> RefPtr<Range> rangeForUnorderedCharacterOffsets(const CharacterOffset&, const CharacterOffset&);
</span><span class="cx"> static RefPtr<Range> rangeForNodeContents(Node*);
</span><span class="lines">@@ -220,6 +221,19 @@
</span><span class="cx"> RefPtr<Range> sentenceForCharacterOffset(const CharacterOffset&);
</span><span class="cx"> CharacterOffset nextSentenceEndCharacterOffset(const CharacterOffset&);
</span><span class="cx"> CharacterOffset previousSentenceStartCharacterOffset(const CharacterOffset&);
</span><ins>+
+ // Bounds
+ CharacterOffset characterOffsetForPoint(const IntPoint&, AccessibilityObject*);
+ IntRect absoluteCaretBoundsForCharacterOffset(const CharacterOffset&);
+ CharacterOffset characterOffsetForBounds(const IntRect&, bool);
+
+ // Lines
+ CharacterOffset endCharacterOffsetOfLine(const CharacterOffset&);
+ CharacterOffset startCharacterOffsetOfLine(const CharacterOffset&);
+
+ // Index
+ CharacterOffset characterOffsetForIndex(int, const AccessibilityObject*);
+ int indexForCharacterOffset(const CharacterOffset&, AccessibilityObject*);
</ins><span class="cx">
</span><span class="cx"> enum AXNotification {
</span><span class="cx"> AXActiveDescendantChanged,
</span><span class="lines">@@ -321,7 +335,6 @@
</span><span class="cx"> void setTextMarkerDataWithCharacterOffset(TextMarkerData&, const CharacterOffset&);
</span><span class="cx"> UChar32 characterAfter(const CharacterOffset&);
</span><span class="cx"> UChar32 characterBefore(const CharacterOffset&);
</span><del>- CharacterOffset startOrEndCharacterOffsetForRange(RefPtr<Range>, bool);
</del><span class="cx"> CharacterOffset characterOffsetForNodeAndOffset(Node&, int, TraverseOption = TraverseOptionDefault);
</span><span class="cx"> CharacterOffset previousBoundary(const CharacterOffset&, BoundarySearchFunction);
</span><span class="cx"> CharacterOffset nextBoundary(const CharacterOffset&, BoundarySearchFunction);
</span><span class="lines">@@ -331,6 +344,9 @@
</span><span class="cx"> CharacterOffset endCharacterOffsetOfParagraph(const CharacterOffset&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
</span><span class="cx"> CharacterOffset startCharacterOffsetOfSentence(const CharacterOffset&);
</span><span class="cx"> CharacterOffset endCharacterOffsetOfSentence(const CharacterOffset&);
</span><ins>+ CharacterOffset characterOffsetForPoint(const IntPoint&);
+ LayoutRect localCaretRectForCharacterOffset(RenderObject*&, const CharacterOffset&);
+ bool shouldSkipBoundary(const CharacterOffset&, const CharacterOffset&);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> AccessibilityObject* rootWebArea();
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1198,6 +1198,20 @@
</span><span class="cx"> return VisiblePositionRange(startPosition, endPosition);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RefPtr<Range> AccessibilityObject::rangeForPlainTextRange(const PlainTextRange& range) const
+{
+ unsigned textLength = getLengthForTextRange();
+ if (range.start + range.length > textLength)
+ return nullptr;
+
+ if (AXObjectCache* cache = axObjectCache()) {
+ CharacterOffset start = cache->characterOffsetForIndex(range.start, this);
+ CharacterOffset end = cache->characterOffsetForIndex(range.start + range.length, this);
+ return cache->rangeForUnorderedCharacterOffsets(start, end);
+ }
+ return nullptr;
+}
+
</ins><span class="cx"> VisiblePositionRange AccessibilityObject::lineRangeForPosition(const VisiblePosition& visiblePosition) const
</span><span class="cx"> {
</span><span class="cx"> VisiblePosition startPosition = startOfLine(visiblePosition);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityObject.h        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -835,10 +835,13 @@
</span><span class="cx"> VisiblePositionRange styleRangeForPosition(const VisiblePosition&) const;
</span><span class="cx"> VisiblePositionRange visiblePositionRangeForRange(const PlainTextRange&) const;
</span><span class="cx"> VisiblePositionRange lineRangeForPosition(const VisiblePosition&) const;
</span><ins>+
+ RefPtr<Range> rangeForPlainTextRange(const PlainTextRange&) const;
</ins><span class="cx">
</span><span class="cx"> String stringForVisiblePositionRange(const VisiblePositionRange&) const;
</span><span class="cx"> String stringForRange(RefPtr<Range>) const;
</span><span class="cx"> virtual IntRect boundsForVisiblePositionRange(const VisiblePositionRange&) const { return IntRect(); }
</span><ins>+ virtual IntRect boundsForRange(const RefPtr<Range>) const { return IntRect(); }
</ins><span class="cx"> int lengthForVisiblePositionRange(const VisiblePositionRange&) const;
</span><span class="cx"> virtual void setSelectedVisiblePositionRange(const VisiblePositionRange&) const { }
</span><span class="cx">
</span><span class="lines">@@ -872,6 +875,7 @@
</span><span class="cx">
</span><span class="cx"> virtual String doAXStringForRange(const PlainTextRange&) const { return String(); }
</span><span class="cx"> virtual IntRect doAXBoundsForRange(const PlainTextRange&) const { return IntRect(); }
</span><ins>+ virtual IntRect doAXBoundsForRangeUsingCharacterOffset(const PlainTextRange&) const { return IntRect(); }
</ins><span class="cx"> String listMarkerTextForNodeAndPosition(Node*, const VisiblePosition&) const;
</span><span class="cx">
</span><span class="cx"> unsigned doAXLineForIndex(unsigned);
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityRenderObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1962,6 +1962,26 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+IntRect AccessibilityRenderObject::boundsForRects(LayoutRect& rect1, LayoutRect& rect2, RefPtr<Range> dataRange) const
+{
+ LayoutRect ourRect = rect1;
+ ourRect.unite(rect2);
+
+ // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
+ if (rect1.maxY() != rect2.maxY()) {
+ LayoutRect boundingBox = dataRange->absoluteBoundingBox();
+ String rangeString = plainText(dataRange.get());
+ if (rangeString.length() > 1 && !boundingBox.isEmpty())
+ ourRect = boundingBox;
+ }
+
+#if PLATFORM(MAC)
+ return m_renderer->view().frameView().contentsToScreen(snappedIntRect(ourRect));
+#else
+ return snappedIntRect(ourRect);
+#endif
+}
+
</ins><span class="cx"> IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const
</span><span class="cx"> {
</span><span class="cx"> if (visiblePositionRange.isNull())
</span><span class="lines">@@ -1985,23 +2005,39 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- LayoutRect ourrect = rect1;
- ourrect.unite(rect2);
</del><ins>+ RefPtr<Range> dataRange = makeRange(range.start, range.end);
+ return boundsForRects(rect1, rect2, dataRange);
+}
+
+IntRect AccessibilityRenderObject::boundsForRange(const RefPtr<Range> range) const
+{
+ if (!range)
+ return IntRect();
</ins><span class="cx">
</span><del>- // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
- if (rect1.maxY() != rect2.maxY()) {
- RefPtr<Range> dataRange = makeRange(range.start, range.end);
- LayoutRect boundingBox = dataRange->absoluteBoundingBox();
- String rangeString = plainText(dataRange.get());
- if (rangeString.length() > 1 && !boundingBox.isEmpty())
- ourrect = boundingBox;
</del><ins>+ AXObjectCache* cache = this->axObjectCache();
+ if (!cache)
+ return IntRect();
+
+ CharacterOffset start = cache->startOrEndCharacterOffsetForRange(range, true);
+ CharacterOffset end = cache->startOrEndCharacterOffsetForRange(range, false);
+
+ LayoutRect rect1 = cache->absoluteCaretBoundsForCharacterOffset(start);
+ LayoutRect rect2 = cache->absoluteCaretBoundsForCharacterOffset(end);
+
+ // readjust for position at the edge of a line. This is to exclude line rect that doesn't need to be accounted in the range bounds.
+ if (rect2.y() != rect1.y()) {
+ CharacterOffset endOfFirstLine = cache->endCharacterOffsetOfLine(start);
+ if (start.isEqual(endOfFirstLine)) {
+ start = cache->nextCharacterOffset(start, false);
+ rect1 = cache->absoluteCaretBoundsForCharacterOffset(start);
+ }
+ if (end.isEqual(endOfFirstLine)) {
+ end = cache->previousCharacterOffset(end, false);
+ rect2 = cache->absoluteCaretBoundsForCharacterOffset(end);
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-#if PLATFORM(MAC)
- return m_renderer->view().frameView().contentsToScreen(snappedIntRect(ourrect));
-#else
- return snappedIntRect(ourrect);
-#endif
</del><ins>+ return boundsForRects(rect1, rect2, range);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePositionRange& range) const
</span><span class="lines">@@ -2196,6 +2232,13 @@
</span><span class="cx"> return IntRect();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+IntRect AccessibilityRenderObject::doAXBoundsForRangeUsingCharacterOffset(const PlainTextRange& range) const
+{
+ if (allowsTextRanges())
+ return boundsForRange(rangeForPlainTextRange(range));
+ return IntRect();
+}
+
</ins><span class="cx"> AccessibilityObject* AccessibilityRenderObject::accessibilityImageMapHitTest(HTMLAreaElement* area, const IntPoint& point) const
</span><span class="cx"> {
</span><span class="cx"> if (!area)
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityRenderObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.h        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -173,6 +173,8 @@
</span><span class="cx"> VisiblePositionRange visiblePositionRange() const override;
</span><span class="cx"> VisiblePositionRange visiblePositionRangeForLine(unsigned) const override;
</span><span class="cx"> IntRect boundsForVisiblePositionRange(const VisiblePositionRange&) const override;
</span><ins>+ IntRect boundsForRange(const RefPtr<Range>) const override;
+ IntRect boundsForRects(LayoutRect&, LayoutRect&, RefPtr<Range>) const;
</ins><span class="cx"> void setSelectedVisiblePositionRange(const VisiblePositionRange&) const override;
</span><span class="cx"> bool supportsARIAFlowTo() const override;
</span><span class="cx"> void ariaFlowToElements(AccessibilityChildrenVector&) const override;
</span><span class="lines">@@ -200,6 +202,7 @@
</span><span class="cx">
</span><span class="cx"> String doAXStringForRange(const PlainTextRange&) const override;
</span><span class="cx"> IntRect doAXBoundsForRange(const PlainTextRange&) const override;
</span><ins>+ IntRect doAXBoundsForRangeUsingCharacterOffset(const PlainTextRange&) const override;
</ins><span class="cx">
</span><span class="cx"> String stringValueForMSAA() const override;
</span><span class="cx"> String stringRoleForMSAA() const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityiosWebAccessibilityObjectWrapperIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -2148,10 +2148,14 @@
</span><span class="cx"> if (!marker)
</span><span class="cx"> return NSNotFound;
</span><span class="cx">
</span><del>- VisibleSelection selection([marker visiblePosition]);
- RefPtr<Range> range = selection.toNormalizedRange();
- NSRange nsRange = [self _convertToNSRange:range.get()];
- return nsRange.location;
</del><ins>+ if (AXObjectCache* cache = m_object->axObjectCache()) {
+ CharacterOffset characterOffset = [marker characterOffset];
+ // Create a collapsed range from the CharacterOffset object.
+ RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(characterOffset, characterOffset);
+ NSRange nsRange = [self _convertToNSRange:range.get()];
+ return nsRange.location;
+ }
+ return NSNotFound;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (NSArray *)textMarkerRange
</span><span class="lines">@@ -2205,11 +2209,17 @@
</span><span class="cx"> VisibleSelection selection = m_object->selection();
</span><span class="cx"> if (selection.isNone())
</span><span class="cx"> return nil;
</span><del>- VisiblePosition startPosition = selection.visibleStart();
- VisiblePosition endPosition = selection.visibleEnd();
</del><ins>+
+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+
+ RefPtr<Range> range = selection.toNormalizedRange();
+ CharacterOffset start = cache->startOrEndCharacterOffsetForRange(range, true);
+ CharacterOffset end = cache->startOrEndCharacterOffsetForRange(range, false);
</ins><span class="cx">
</span><del>- WebAccessibilityTextMarker* startMarker = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:startPosition cache:m_object->axObjectCache()];
- WebAccessibilityTextMarker* endMarker = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:endPosition cache:m_object->axObjectCache()];
</del><ins>+ WebAccessibilityTextMarker* startMarker = [WebAccessibilityTextMarker textMarkerWithCharacterOffset:start cache:cache];
+ WebAccessibilityTextMarker* endMarker = [WebAccessibilityTextMarker textMarkerWithCharacterOffset:end cache:cache];
</ins><span class="cx"> if (!startMarker || !endMarker)
</span><span class="cx"> return nil;
</span><span class="cx">
</span><span class="lines">@@ -2224,11 +2234,13 @@
</span><span class="cx"> RefPtr<Range> range = [self _convertToDOMRange:NSMakeRange(position, 0)];
</span><span class="cx"> if (!range)
</span><span class="cx"> return nil;
</span><ins>+
+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
</ins><span class="cx">
</span><del>- VisibleSelection selection = VisibleSelection(*range, DOWNSTREAM);
-
- VisiblePosition visiblePosition = selection.visibleStart();
- return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:visiblePosition cache:m_object->axObjectCache()];
</del><ins>+ CharacterOffset characterOffset = cache->startOrEndCharacterOffsetForRange(range, true);
+ return [WebAccessibilityTextMarker textMarkerWithCharacterOffset:characterOffset cache:cache];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (id)_stringForRange:(NSRange)range attributed:(BOOL)attributed
</span><span class="lines">@@ -2405,15 +2417,14 @@
</span><span class="cx"> if (![self _prepareAccessibilityCall])
</span><span class="cx"> return CGRectZero;
</span><span class="cx">
</span><del>- if ([array count] != 2)
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
</ins><span class="cx"> return CGRectZero;
</span><ins>+ RefPtr<Range> range = [self rangeForTextMarkers:array];
+ if (!range)
+ return CGRectZero;
</ins><span class="cx">
</span><del>- WebAccessibilityTextMarker* startMarker = [array objectAtIndex:0];
- WebAccessibilityTextMarker* endMarker = [array objectAtIndex:1];
- if (![startMarker isKindOfClass:[WebAccessibilityTextMarker class]] || ![endMarker isKindOfClass:[WebAccessibilityTextMarker class]])
- return CGRectZero;
-
- IntRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange([startMarker visiblePosition], [endMarker visiblePosition]));
</del><ins>+ IntRect rect = m_object->boundsForRange(range);
</ins><span class="cx"> return [self convertRectToScreenSpace:rect];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2422,8 +2433,11 @@
</span><span class="cx"> if (![self _prepareAccessibilityCall])
</span><span class="cx"> return nil;
</span><span class="cx">
</span><del>- VisiblePosition pos = m_object->visiblePositionForPoint(IntPoint(point));
- return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:pos cache:m_object->axObjectCache()];
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+ CharacterOffset characterOffset = cache->characterOffsetForPoint(IntPoint(point), m_object);
+ return [WebAccessibilityTextMarker textMarkerWithCharacterOffset:characterOffset cache:cache];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (WebAccessibilityTextMarker *)nextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -3776,8 +3776,8 @@
</span><span class="cx"> - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
</span><span class="cx"> {
</span><span class="cx"> PlainTextRange textRange = PlainTextRange(range.location, range.length);
</span><del>- VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
- return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
</del><ins>+ RefPtr<Range> webRange = m_object->rangeForPlainTextRange(textRange);
+ return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromRange:webRange]];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (NSRange)_convertToNSRange:(Range*)range
</span><span class="lines">@@ -3804,8 +3804,13 @@
</span><span class="cx"> if (!marker)
</span><span class="cx"> return NSNotFound;
</span><span class="cx">
</span><del>- VisibleSelection selection([self visiblePositionForTextMarker:marker]);
- return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
</del><ins>+ if (AXObjectCache* cache = m_object->axObjectCache()) {
+ CharacterOffset characterOffset = [self characterOffsetForTextMarker:marker];
+ // Create a collapsed range from the CharacterOffset object.
+ RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(characterOffset, characterOffset);
+ return [self _convertToNSRange:range.get()].location;
+ }
+ return NSNotFound;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (id)_textMarkerForIndex:(NSInteger)textIndex
</span><span class="lines">@@ -3818,8 +3823,11 @@
</span><span class="cx"> if (!textRange || !textRange->boundaryPointsValid())
</span><span class="cx"> return nil;
</span><span class="cx">
</span><del>- VisiblePosition position(textRange->startPosition());
- return [self textMarkerForVisiblePosition:position];
</del><ins>+ if (AXObjectCache* cache = m_object->axObjectCache()) {
+ CharacterOffset characterOffset = cache->startOrEndCharacterOffsetForRange(textRange, true);
+ return [self textMarkerForCharacterOffset:characterOffset];
+ }
+ return nil;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // The RTF representation of the text associated with this accessibility object that is
</span><span class="lines">@@ -3907,6 +3915,10 @@
</span><span class="cx"> if (![self updateObjectBackingStore])
</span><span class="cx"> return nil;
</span><span class="cx">
</span><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+
</ins><span class="cx"> // common parameter type check/casting. Nil checks in handlers catch wrong type case.
</span><span class="cx"> // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
</span><span class="cx"> // a parameter of the wrong type.
</span><span class="lines">@@ -3964,11 +3976,13 @@
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute]) {
</span><span class="cx"> IntRect webCoreRect = [self screenToContents:enclosingIntRect(rect)];
</span><del>- return [self textMarkerForVisiblePosition:m_object->visiblePositionForBounds(webCoreRect, LastVisiblePositionForBounds)];
</del><ins>+ CharacterOffset characterOffset = cache->characterOffsetForBounds(webCoreRect, false);
+ return [self textMarkerForCharacterOffset:characterOffset];
</ins><span class="cx"> }
</span><span class="cx"> if ([attribute isEqualToString:NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute]) {
</span><span class="cx"> IntRect webCoreRect = [self screenToContents:enclosingIntRect(rect)];
</span><del>- return [self textMarkerForVisiblePosition:m_object->visiblePositionForBounds(webCoreRect, FirstVisiblePositionForBounds)];
</del><ins>+ CharacterOffset characterOffset = cache->characterOffsetForBounds(webCoreRect, true);
+ return [self textMarkerForCharacterOffset:characterOffset];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute]) {
</span><span class="lines">@@ -4017,30 +4031,35 @@
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
</span><span class="cx"> IntPoint webCorePoint = IntPoint(point);
</span><del>- return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
</del><ins>+ if (!pointSet)
+ return nil;
+ CharacterOffset characterOffset = cache->characterOffsetForPoint(webCorePoint, m_object);
+ return [self textMarkerForCharacterOffset:characterOffset];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
</span><del>- VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
- NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
</del><ins>+ RefPtr<Range> range = [self rangeForTextMarkerRange:textMarkerRange];
+ NSRect rect = m_object->boundsForRange(range);
</ins><span class="cx"> return [NSValue valueWithRect:rect];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
</span><del>- VisiblePosition start = m_object->visiblePositionForIndex(range.location);
- VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
</del><ins>+ CharacterOffset start = cache->characterOffsetForIndex(range.location, m_object);
+ CharacterOffset end = cache->characterOffsetForIndex(range.location+range.length, m_object);
</ins><span class="cx"> if (start.isNull() || end.isNull())
</span><span class="cx"> return nil;
</span><del>- NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
</del><ins>+ RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(start, end);
+ NSRect rect = m_object->boundsForRange(range);
</ins><span class="cx"> return [NSValue valueWithRect:rect];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
</span><del>- VisiblePosition start = m_object->visiblePositionForIndex(range.location);
- VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
</del><ins>+ CharacterOffset start = cache->characterOffsetForIndex(range.location, m_object);
+ CharacterOffset end = cache->characterOffsetForIndex(range.location + range.length, m_object);
</ins><span class="cx"> if (start.isNull() || end.isNull())
</span><span class="cx"> return nil;
</span><del>- return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
</del><ins>+ RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(start, end);
+ return m_object->stringForRange(range);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
</span><span class="lines">@@ -4055,9 +4074,6 @@
</span><span class="cx"> if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))
</span><span class="cx"> return nil;
</span><span class="cx">
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset1 = [self characterOffsetForTextMarker:textMarker1];
</span><span class="cx"> CharacterOffset characterOffset2 = [self characterOffsetForTextMarker:textMarker2];
</span><span class="cx"> RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(characterOffset1, characterOffset2);
</span><span class="lines">@@ -4075,18 +4091,12 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> RefPtr<Range> range = cache->leftWordRange(characterOffset);
</span><span class="cx"> return [self textMarkerRangeFromRange:range];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> RefPtr<Range> range = cache->rightWordRange(characterOffset);
</span><span class="cx"> return [self textMarkerRangeFromRange:range];
</span><span class="lines">@@ -4105,36 +4115,24 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> RefPtr<Range> range = cache->sentenceForCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerRangeFromRange:range];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> RefPtr<Range> range = cache->paragraphForCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerRangeFromRange:range];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset nextEnd = cache->nextWordEndCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:nextEnd];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset previousStart = cache->previousWordStartCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:previousStart];
</span><span class="lines">@@ -4151,36 +4149,24 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset nextEnd = cache->nextSentenceEndCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:nextEnd];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset previousStart = cache->previousSentenceStartCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:previousStart];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset nextEnd = cache->nextParagraphEndCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:nextEnd];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
</span><del>- AXObjectCache* cache = m_object->axObjectCache();
- if (!cache)
- return nil;
</del><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset previousStart = cache->previousParagraphStartCharacterOffset(characterOffset);
</span><span class="cx"> return [self textMarkerForCharacterOffset:previousStart];
</span><span class="lines">@@ -4276,7 +4262,7 @@
</span><span class="cx"> if (!rangeSet)
</span><span class="cx"> return nil;
</span><span class="cx"> PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
</span><del>- NSRect rect = m_object->doAXBoundsForRange(plainTextRange);
</del><ins>+ NSRect rect = m_object->doAXBoundsForRangeUsingCharacterOffset(plainTextRange);
</ins><span class="cx"> return [NSValue valueWithRect:rect];
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreeditinghtmleditingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/htmlediting.cpp (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/htmlediting.cpp        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/editing/htmlediting.cpp        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -1320,9 +1320,14 @@
</span><span class="cx"> RenderObject* renderer;
</span><span class="cx"> LayoutRect localRect = caretPosition.localCaretRect(renderer);
</span><span class="cx">
</span><ins>+ return localCaretRectInRendererForRect(localRect, caretPosition.deepEquivalent().deprecatedNode(), renderer, caretPainter);
+}
+
+LayoutRect localCaretRectInRendererForRect(LayoutRect& localRect, Node* node, RenderObject* renderer, RenderBlock*& caretPainter)
+{
</ins><span class="cx"> // Get the renderer that will be responsible for painting the caret
</span><span class="cx"> // (which is either the renderer we just found, or one of its containers).
</span><del>- caretPainter = rendererForCaretPainting(caretPosition.deepEquivalent().deprecatedNode());
</del><ins>+ caretPainter = rendererForCaretPainting(node);
</ins><span class="cx">
</span><span class="cx"> // Compute an offset between the renderer and the caretPainter.
</span><span class="cx"> while (renderer != caretPainter) {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditinghtmleditingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/htmlediting.h (197981 => 197982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/htmlediting.h        2016-03-11 01:49:22 UTC (rev 197981)
+++ trunk/Source/WebCore/editing/htmlediting.h        2016-03-11 02:37:46 UTC (rev 197982)
</span><span class="lines">@@ -269,6 +269,7 @@
</span><span class="cx">
</span><span class="cx"> RenderBlock* rendererForCaretPainting(Node*);
</span><span class="cx"> LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition&, RenderBlock*&);
</span><ins>+LayoutRect localCaretRectInRendererForRect(LayoutRect&, Node*, RenderObject*, RenderBlock*&);
</ins><span class="cx"> IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect&);
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>