<!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>[196546] 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/196546">196546</a></dd>
<dt>Author</dt> <dd>n_wang@apple.com</dd>
<dt>Date</dt> <dd>2016-02-12 21:24:24 -0800 (Fri, 12 Feb 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>AX: Implement paragraph related text marker functions using TextIterator
https://bugs.webkit.org/show_bug.cgi?id=154098
<rdar://problem/24269675>
Reviewed by Chris Fleizach.
Source/WebCore:
Using CharacterOffset to implement paragraph related text marker calls. Reused
logic from VisibleUnits class. And refactored textMarkerForCharacterOffset method
to get better performance. Also fixed an issue where we can't navigate through a text
node with line breaks in it using next/previousCharacterOffset call.
Test: accessibility/mac/text-marker-paragraph-nav.html
* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::traverseToOffsetInRange):
(WebCore::AXObjectCache::startOrEndTextMarkerDataForRange):
(WebCore::AXObjectCache::characterOffsetForNodeAndOffset):
(WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
(WebCore::AXObjectCache::textMarkerDataForNextCharacterOffset):
(WebCore::AXObjectCache::textMarkerDataForPreviousCharacterOffset):
(WebCore::AXObjectCache::nextNode):
(WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
(WebCore::AXObjectCache::nextCharacterOffset):
(WebCore::AXObjectCache::previousCharacterOffset):
(WebCore::startWordBoundary):
(WebCore::AXObjectCache::startCharacterOffsetOfWord):
(WebCore::AXObjectCache::endCharacterOffsetOfWord):
(WebCore::AXObjectCache::previousWordStartCharacterOffset):
(WebCore::AXObjectCache::previousWordBoundary):
(WebCore::AXObjectCache::startCharacterOffsetOfParagraph):
(WebCore::AXObjectCache::endCharacterOffsetOfParagraph):
(WebCore::AXObjectCache::paragraphForCharacterOffset):
(WebCore::AXObjectCache::nextParagraphEndCharacterOffset):
(WebCore::AXObjectCache::previousParagraphStartCharacterOffset):
(WebCore::AXObjectCache::rootAXEditableElement):
* accessibility/AXObjectCache.h:
(WebCore::CharacterOffset::remaining):
(WebCore::CharacterOffset::isNull):
(WebCore::CharacterOffset::isEqual):
(WebCore::AXObjectCache::isNodeInUse):
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(+[WebAccessibilityTextMarker textMarkerWithCharacterOffset:cache:]):
(-[WebAccessibilityObjectWrapper nextMarkerForCharacterOffset:]):
(-[WebAccessibilityObjectWrapper previousMarkerForCharacterOffset:]):
(-[WebAccessibilityObjectWrapper rangeForTextMarkers:]):
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(startOrEndTextmarkerForRange):
(nextTextMarkerForCharacterOffset):
(previousTextMarkerForCharacterOffset):
(-[WebAccessibilityObjectWrapper nextTextMarkerForCharacterOffset:]):
(-[WebAccessibilityObjectWrapper previousTextMarkerForCharacterOffset:]):
(-[WebAccessibilityObjectWrapper textMarkerForCharacterOffset:]):
(textMarkerForCharacterOffset):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
(-[WebAccessibilityObjectWrapper nextTextMarkerForNode:offset:]): Deleted.
(-[WebAccessibilityObjectWrapper previousTextMarkerForNode:offset:]): Deleted.
(-[WebAccessibilityObjectWrapper textMarkerForNode:offset:ignoreStart:]): Deleted.
(-[WebAccessibilityObjectWrapper textMarkerForNode:offset:]): Deleted.
* editing/VisibleUnits.cpp:
(WebCore::nextSentencePosition):
(WebCore::findStartOfParagraph):
(WebCore::findEndOfParagraph):
(WebCore::startOfParagraph):
(WebCore::endOfParagraph):
* editing/VisibleUnits.h:
Tools:
* DumpRenderTree/AccessibilityUIElement.cpp:
(nextWordEndTextMarkerForTextMarkerCallback):
(paragraphTextMarkerRangeForTextMarkerCallback):
(previousParagraphStartTextMarkerForTextMarkerCallback):
(nextParagraphEndTextMarkerForTextMarkerCallback):
(setSelectedVisibleTextRangeCallback):
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
(AccessibilityUIElement::getJSClass):
* DumpRenderTree/AccessibilityUIElement.h:
* DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
* DumpRenderTree/mac/AccessibilityUIElementMac.mm:
(AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
(AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
(AccessibilityUIElement::supportedActions):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
(WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::mathPostscriptsDescription):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
(WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
(WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
(WTR::_convertMathMultiscriptPairsToString):
LayoutTests:
* accessibility/mac/text-marker-paragraph-nav-expected.txt: Added.
* accessibility/mac/text-marker-paragraph-nav.html: Added.
* accessibility/text-marker/text-marker-previous-next-expected.txt:
* accessibility/text-marker/text-marker-previous-next.html:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnextexpectedtxt">trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnexthtml">trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.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="#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="#trunkSourceWebCoreeditingVisibleUnitscpp">trunk/Source/WebCore/editing/VisibleUnits.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitsh">trunk/Source/WebCore/editing/VisibleUnits.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsDumpRenderTreeAccessibilityUIElementcpp">trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp</a></li>
<li><a href="#trunkToolsDumpRenderTreeAccessibilityUIElementh">trunk/Tools/DumpRenderTree/AccessibilityUIElement.h</a></li>
<li><a href="#trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm">trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm</a></li>
<li><a href="#trunkToolsDumpRenderTreemacAccessibilityUIElementMacmm">trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementh">trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleBindingsAccessibilityUIElementidl">trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm">trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundlemacAccessibilityUIElementMacmm">trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerparagraphnavexpectedtxt">trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav-expected.txt</a></li>
<li><a href="#trunkLayoutTestsaccessibilitymactextmarkerparagraphnavhtml">trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/LayoutTests/ChangeLog        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-02-12 Nan Wang <n_wang@apple.com>
+
+ AX: Implement paragraph related text marker functions using TextIterator
+ https://bugs.webkit.org/show_bug.cgi?id=154098
+ <rdar://problem/24269675>
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/mac/text-marker-paragraph-nav-expected.txt: Added.
+ * accessibility/mac/text-marker-paragraph-nav.html: Added.
+ * accessibility/text-marker/text-marker-previous-next-expected.txt:
+ * accessibility/text-marker/text-marker-previous-next.html:
+
</ins><span class="cx"> 2016-02-12 Saam barati <sbarati@apple.com>
</span><span class="cx">
</span><span class="cx"> [ES6] we have an incorrect syntax error when a callee of a function expression has the same name as a top-level lexical declaration
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerparagraphnavexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav-expected.txt (0 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav-expected.txt         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav-expected.txt        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+paragraph test
+Test Contenteditable is working.
+c d
+test audio file
+can't select
+巧克力 是食物吗?
+كيف حالك؟
+both spaces
+line breaks
+some
+text
+this is my first paragraph. Of text. it has some text.
+this is my second paragraph. Of text. it has some text.
+this is my third paragraph. Of text. it has some text.
+
+This tests that paragraph navigation is working correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Current character is: p
+Current paragraph is: paragraph test
+Pre paragraph start to next paragraph end: paragraph test
+
+Current character is: T
+Current paragraph is: Test Content
+Pre paragraph start to next paragraph end: Test Content
+
+Current character is: c
+Current paragraph is: c [ATTACHMENT]d
+Pre paragraph start to next paragraph end: c [ATTACHMENT]d
+
+Current character is: d
+Current paragraph is: c [ATTACHMENT]d
+Pre paragraph start to next paragraph end: c [ATTACHMENT]d
+test audio file
+
+Current character is: t
+Current paragraph is: test audio [ATTACHMENT]file
+Pre paragraph start to next paragraph end: test audio [ATTACHMENT]file
+
+Current character is: c
+Current paragraph is: can't select
+Pre paragraph start to next paragraph end: can't select
+
+Current character is: 巧
+Current paragraph is: 巧克力 是食物吗?
+Pre paragraph start to next paragraph end: 巧克力 是食物吗?
+
+Current character is: ك
+Current paragraph is: كيف حالك؟
+Pre paragraph start to next paragraph end: كيف حالك؟
+
+Current character is: b
+Current paragraph is: both spaces
+Pre paragraph start to next paragraph end: both spaces
+
+Current character is: i
+Current paragraph is: line breaks
+Pre paragraph start to next paragraph end: line breaks
+
+Current character is: s
+Current paragraph is: some
+Pre paragraph start to next paragraph end: some
+
+Current character is: t
+Current paragraph is: text
+Pre paragraph start to next paragraph end: text
+
+Paragraph: this is my first paragraph. Of text. it has some text.
+Paragraph: this is my second paragraph. Of text. it has some text.
+Paragraph: this is my third paragraph. Of text. it has some text.
+Paragraph: this is my third paragraph. Of text. it has some text.
+Paragraph: this is my second paragraph. Of text. it has some text.
+Paragraph: this is my first paragraph. Of text. it has some text.
+Test going forward.
+End paragraph: text
+
+Test going backwards.
+Start paragraph: paragraph test
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsaccessibilitymactextmarkerparagraphnavhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav.html (0 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav.html         (rev 0)
+++ trunk/LayoutTests/accessibility/mac/text-marker-paragraph-nav.html        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -0,0 +1,219 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<style>
+.userselect { user-select: none; -webkit-user-select: none; }
+</style>
+<body id="body">
+
+<div id="text1" tabindex="0">
+para<span>graph</span>
+test
+</div>
+
+<div id="text2">
+Test Content<span contenteditable="true">editable is working.</span>
+</div>
+
+<div id="text3">
+c <img src="#" aria-label="blah" style="background-color: #aaaaaa; width: 100px; height: 100px;">d
+</div>
+
+<div id="text4">
+test audio <audio controls><source src="test.mp3" type="audio/mpeg"></audio>file
+</div>
+
+<div class="" id="text5">can't select</div>
+
+<div id="text6">
+巧克力
+是食物吗?
+</div>
+
+<div id="text6a">
+كيف حالك؟
+</div>
+
+<pre id="text7">
+both spaces
+line breaks
+</pre>
+
+<div id="text8">
+some<br>text
+</div>
+
+<div id="text9">this is my first paragraph. Of text. it has some text.<br>
+this is my second paragraph. Of text. it has some text.<br>
+this is my third paragraph. Of text. it has some text.<br><br>
+</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+ description("This tests that paragraph navigation is working correctly.");
+
+ if (window.accessibilityController) {
+
+ // Check that we can get the paragraph range with span tag.
+ var text = accessibilityController.accessibleElementById("text1");
+ var textMarkerRange = text.textMarkerRangeForElement(text);
+ var startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ var currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ // Check with contenteditable.
+ text = accessibilityController.accessibleElementById("text2");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ // Check with replaced elements.
+ text = accessibilityController.accessibleElementById("text3");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+ currentMarker = advanceAndVerify(currentMarker, 3, text);
+ // Audio tag.
+ text = accessibilityController.accessibleElementById("text4");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ // Check with user-select:none.
+ text = accessibilityController.accessibleElementById("text5");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ // Multi-languages.
+ text = accessibilityController.accessibleElementById("text6");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ text = accessibilityController.accessibleElementById("text6a");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+
+ // Check the case with pre tag.
+ text = accessibilityController.accessibleElementById("text7");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+ currentMarker = advanceAndVerify(currentMarker, 15, text);
+
+ // Check the case with br tag.
+ text = accessibilityController.accessibleElementById("text8");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = advanceAndVerify(startMarker, 1, text);
+ currentMarker = advanceAndVerify(currentMarker, 5, text);
+
+ // Check getting the correct paragraphs
+ text = accessibilityController.accessibleElementById("text9");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ startMarker = text.nextTextMarker(startMarker);
+ var endMarker = text.endTextMarkerForTextMarkerRange(textMarkerRange);
+ verifyParagraphs(text, startMarker, 3);
+
+ // Check the paragraph marker runs from start to end, and backwards.
+ // Make sure it won't hang.
+ verifyDocument(text);
+
+
+ function advanceAndVerify(currentMarker, offset, obj) {
+ var previousMarker = currentMarker;
+ for (var i = 0; i < offset; i++) {
+ previousMarker = currentMarker;
+ currentMarker = obj.nextTextMarker(previousMarker);
+ }
+ verifyParagraphRangeForTextMarker(previousMarker, currentMarker, obj);
+ return currentMarker;
+ }
+
+ function replaceAttachmentInString(str) {
+ str = str.replace(String.fromCharCode(65532), "[ATTACHMENT]");
+ return str;
+ }
+
+ function verifyParagraphRangeForTextMarker(preMarker, textMarker, obj) {
+ var markerRange = obj.textMarkerRangeForMarkers(preMarker, textMarker);
+ var currentCharacter = replaceAttachmentInString(obj.stringForTextMarkerRange(markerRange));
+ debug("Current character is: " + currentCharacter);
+
+ var paragraphRange = obj.paragraphTextMarkerRangeForTextMarker(textMarker);
+ var paragraph = replaceAttachmentInString(obj.stringForTextMarkerRange(paragraphRange));
+ debug("Current paragraph is: " + paragraph);
+
+ var preStart = obj.previousParagraphStartTextMarkerForTextMarker(textMarker);
+ var nextEnd = obj.nextParagraphEndTextMarkerForTextMarker(textMarker);
+ var preAndNextParagraphRange = obj.textMarkerRangeForMarkers(preStart, nextEnd);
+ var preAndNextParagraph = replaceAttachmentInString(obj.stringForTextMarkerRange(preAndNextParagraphRange));
+ debug("Pre paragraph start to next paragraph end: " + preAndNextParagraph + "\n");
+ }
+
+ function verifyParagraphs(obj, startMarker, paragraphCount) {
+ // Move to the end of first paragraph, so the first paragraph
+ // won't print twice.
+ var current = obj.nextParagraphEndTextMarkerForTextMarker(startMarker);
+ var i = 0;
+ while(i < paragraphCount) {
+ var currRange = obj.paragraphTextMarkerRangeForTextMarker(current);
+ var currParagraph = obj.stringForTextMarkerRange(currRange);
+ debug("Paragraph: " + currParagraph);
+ current = obj.nextParagraphEndTextMarkerForTextMarker(current);
+ i++;
+ }
+
+ // Backwards.
+ current = obj.previousParagraphStartTextMarkerForTextMarker(current);
+ i = 0;
+ while(i < paragraphCount) {
+ var currRange = obj.paragraphTextMarkerRangeForTextMarker(current);
+ var currParagraph = obj.stringForTextMarkerRange(currRange);
+ debug("Paragraph: " + currParagraph);
+ current = obj.previousParagraphStartTextMarkerForTextMarker(current);
+ i++;
+ }
+ }
+
+ function verifyDocument(obj) {
+ var start = obj.startTextMarker;
+
+ // Going forward.
+ debug("Test going forward.");
+ var current = start;
+ var end = "text";
+ var currParagraph = "";
+ while(currParagraph != end) {
+ var currRange = obj.paragraphTextMarkerRangeForTextMarker(current);
+ currParagraph = obj.stringForTextMarkerRange(currRange);
+ current = obj.nextParagraphEndTextMarkerForTextMarker(current);
+ }
+ debug("End paragraph: " + replaceAttachmentInString(currParagraph));
+
+ // Going backwards.
+ debug("\nTest going backwards.");
+ var start = "paragraph test";
+ currParagraph = "";
+ while(currParagraph != start) {
+ var currentRange = obj.paragraphTextMarkerRangeForTextMarker(current);
+ currParagraph = obj.stringForTextMarkerRange(currentRange);
+ current = obj.previousParagraphStartTextMarkerForTextMarker(current);
+ }
+ debug("Start paragraph: " + replaceAttachmentInString(currParagraph));
+ }
+ }
+
+</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="trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnextexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next-expected.txt        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -4,6 +4,7 @@
</span><span class="cx"> c d
</span><span class="cx">
</span><span class="cx"> can't select
</span><ins>+abc de f
</ins><span class="cx"> This tests the next/previous text marker functions are implemented 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">@@ -25,6 +26,8 @@
</span><span class="cx"> PASS !psw.accessibilityElementForTextMarker(start) is true
</span><span class="cx"> PASS text2.accessibilityElementForTextMarker(currentMarker).isEqual(text3) is true
</span><span class="cx"> PASS text2.accessibilityElementForTextMarker(currentMarker).isEqual(text2.childAtIndex(2)) is true
</span><ins>+PASS text.stringForTextMarkerRange(markerRange) is 'f'
+PASS text.stringForTextMarkerRange(markerRange) is 'a'
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx">
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsaccessibilitytextmarkertextmarkerpreviousnexthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/LayoutTests/accessibility/text-marker/text-marker-previous-next.html        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -20,6 +20,12 @@
</span><span class="cx">
</span><span class="cx"> <div class="userselect" id="text3">can't select</div>
</span><span class="cx">
</span><ins>+<div id="text4">
+abc
+de
+f
+</div>
+
</ins><span class="cx"> <p id="description"></p>
</span><span class="cx"> <div id="console"></div>
</span><span class="cx">
</span><span class="lines">@@ -135,6 +141,27 @@
</span><span class="cx"> currentMarker = text2.previousTextMarker(currentMarker);
</span><span class="cx"> shouldBeTrue("text2.accessibilityElementForTextMarker(currentMarker).isEqual(text2.childAtIndex(2))");
</span><span class="cx">
</span><ins>+
+ // Make sure that text node with line breaks, we can go through it with next/previous call.
+ text = accessibilityController.accessibleElementById("text4");
+ textMarkerRange = text.textMarkerRangeForElement(text);
+ startMarker = text.startTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = startMarker;
+ for (var i = 0; i < 8; i++) {
+ previousMarker = currentMarker;
+ currentMarker = text.nextTextMarker(currentMarker);
+ }
+ markerRange = text.textMarkerRangeForMarkers(previousMarker, currentMarker)
+ shouldBe("text.stringForTextMarkerRange(markerRange)", "'f'");
+
+ endMarker = text.endTextMarkerForTextMarkerRange(textMarkerRange);
+ currentMarker = endMarker;
+ for (var i = 0; i < 7; i++) {
+ currentMarker = text.previousTextMarker(currentMarker);
+ }
+ markerRange = text.textMarkerRangeForMarkers(startMarker, currentMarker)
+ shouldBe("text.stringForTextMarkerRange(markerRange)", "'a'");
+
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/ChangeLog        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1,3 +1,71 @@
</span><ins>+2016-02-12 Nan Wang <n_wang@apple.com>
+
+ AX: Implement paragraph related text marker functions using TextIterator
+ https://bugs.webkit.org/show_bug.cgi?id=154098
+ <rdar://problem/24269675>
+
+ Reviewed by Chris Fleizach.
+
+ Using CharacterOffset to implement paragraph related text marker calls. Reused
+ logic from VisibleUnits class. And refactored textMarkerForCharacterOffset method
+ to get better performance. Also fixed an issue where we can't navigate through a text
+ node with line breaks in it using next/previousCharacterOffset call.
+
+ Test: accessibility/mac/text-marker-paragraph-nav.html
+
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::AXObjectCache::traverseToOffsetInRange):
+ (WebCore::AXObjectCache::startOrEndTextMarkerDataForRange):
+ (WebCore::AXObjectCache::characterOffsetForNodeAndOffset):
+ (WebCore::AXObjectCache::textMarkerDataForCharacterOffset):
+ (WebCore::AXObjectCache::textMarkerDataForNextCharacterOffset):
+ (WebCore::AXObjectCache::textMarkerDataForPreviousCharacterOffset):
+ (WebCore::AXObjectCache::nextNode):
+ (WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
+ (WebCore::AXObjectCache::nextCharacterOffset):
+ (WebCore::AXObjectCache::previousCharacterOffset):
+ (WebCore::startWordBoundary):
+ (WebCore::AXObjectCache::startCharacterOffsetOfWord):
+ (WebCore::AXObjectCache::endCharacterOffsetOfWord):
+ (WebCore::AXObjectCache::previousWordStartCharacterOffset):
+ (WebCore::AXObjectCache::previousWordBoundary):
+ (WebCore::AXObjectCache::startCharacterOffsetOfParagraph):
+ (WebCore::AXObjectCache::endCharacterOffsetOfParagraph):
+ (WebCore::AXObjectCache::paragraphForCharacterOffset):
+ (WebCore::AXObjectCache::nextParagraphEndCharacterOffset):
+ (WebCore::AXObjectCache::previousParagraphStartCharacterOffset):
+ (WebCore::AXObjectCache::rootAXEditableElement):
+ * accessibility/AXObjectCache.h:
+ (WebCore::CharacterOffset::remaining):
+ (WebCore::CharacterOffset::isNull):
+ (WebCore::CharacterOffset::isEqual):
+ (WebCore::AXObjectCache::isNodeInUse):
+ * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+ (+[WebAccessibilityTextMarker textMarkerWithCharacterOffset:cache:]):
+ (-[WebAccessibilityObjectWrapper nextMarkerForCharacterOffset:]):
+ (-[WebAccessibilityObjectWrapper previousMarkerForCharacterOffset:]):
+ (-[WebAccessibilityObjectWrapper rangeForTextMarkers:]):
+ * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+ (startOrEndTextmarkerForRange):
+ (nextTextMarkerForCharacterOffset):
+ (previousTextMarkerForCharacterOffset):
+ (-[WebAccessibilityObjectWrapper nextTextMarkerForCharacterOffset:]):
+ (-[WebAccessibilityObjectWrapper previousTextMarkerForCharacterOffset:]):
+ (-[WebAccessibilityObjectWrapper textMarkerForCharacterOffset:]):
+ (textMarkerForCharacterOffset):
+ (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+ (-[WebAccessibilityObjectWrapper nextTextMarkerForNode:offset:]): Deleted.
+ (-[WebAccessibilityObjectWrapper previousTextMarkerForNode:offset:]): Deleted.
+ (-[WebAccessibilityObjectWrapper textMarkerForNode:offset:ignoreStart:]): Deleted.
+ (-[WebAccessibilityObjectWrapper textMarkerForNode:offset:]): Deleted.
+ * editing/VisibleUnits.cpp:
+ (WebCore::nextSentencePosition):
+ (WebCore::findStartOfParagraph):
+ (WebCore::findEndOfParagraph):
+ (WebCore::startOfParagraph):
+ (WebCore::endOfParagraph):
+ * editing/VisibleUnits.h:
+
</ins><span class="cx"> 2016-02-12 Ryan Haddad <ryanhaddad@apple.com>
</span><span class="cx">
</span><span class="cx"> Reset results for bindings tests after r196520
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAXObjectCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -83,6 +83,7 @@
</span><span class="cx"> #include "ScrollView.h"
</span><span class="cx"> #include "TextBoundaries.h"
</span><span class="cx"> #include "TextIterator.h"
</span><ins>+#include "htmlediting.h"
</ins><span class="cx"> #include <wtf/DataLog.h>
</span><span class="cx">
</span><span class="cx"> #if ENABLE(VIDEO)
</span><span class="lines">@@ -1469,6 +1470,9 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // Sometimes text contents in a node are splitted into several iterations, so that iterator.range()->startOffset()
+ // might not be the correct character count. Here we use a previousNode object to keep track of that.
+ Node* previousNode = nullptr;
</ins><span class="cx"> for (; !iterator.atEnd(); iterator.advance()) {
</span><span class="cx"> int currentLength = iterator.text().length();
</span><span class="cx"> bool hasReplacedNodeOrBR = false;
</span><span class="lines">@@ -1497,22 +1501,27 @@
</span><span class="cx"> if (childNode && childNode->renderer() && childNode->renderer()->isBR()) {
</span><span class="cx"> currentNode = childNode;
</span><span class="cx"> hasReplacedNodeOrBR = true;
</span><del>- } else
</del><ins>+ } else if (currentNode != previousNode)
</ins><span class="cx"> continue;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> offsetSoFar += currentLength;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- lastLength = currentLength;
- lastStartOffset = hasReplacedNodeOrBR ? 0 : iterator.range()->startOffset();
</del><ins>+ if (currentNode == previousNode)
+ lastLength += currentLength;
+ else {
+ lastLength = currentLength;
+ lastStartOffset = hasReplacedNodeOrBR ? 0 : iterator.range()->startOffset();
+ }
</ins><span class="cx">
</span><span class="cx"> // Break early if we have advanced enough characters.
</span><span class="cx"> if (!toNodeEnd && offsetSoFar >= offset) {
</span><del>- offsetInCharacter = offset - (offsetSoFar - currentLength);
</del><ins>+ offsetInCharacter = offset - (offsetSoFar - lastLength);
</ins><span class="cx"> finished = true;
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ previousNode = currentNode;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (!finished) {
</span><span class="lines">@@ -1707,15 +1716,18 @@
</span><span class="cx"> setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-CharacterOffset AXObjectCache::characterOffsetForNodeAndOffset(Node& node, int offset, bool toNodeEnd, bool ignoreStart)
</del><ins>+CharacterOffset AXObjectCache::characterOffsetForNodeAndOffset(Node& node, int offset, TraverseOption option)
</ins><span class="cx"> {
</span><span class="cx"> Node* domNode = &node;
</span><span class="cx"> if (!domNode)
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><ins>+ bool toNodeEnd = option & TraverseOptionToNodeEnd;
+ bool includeStart = option & TraverseOptionIncludeStart;
+
</ins><span class="cx"> // ignoreStart is used to determine if we should go to previous node or
</span><span class="cx"> // stay in current node when offset is 0.
</span><del>- if (!toNodeEnd && (offset < 0 || (!offset && ignoreStart))) {
</del><ins>+ if (!toNodeEnd && (offset < 0 || (!offset && !includeStart))) {
</ins><span class="cx"> // Set the offset to the amount of characters we need to go backwards.
</span><span class="cx"> offset = - offset;
</span><span class="cx"> CharacterOffset charOffset = CharacterOffset();
</span><span class="lines">@@ -1723,14 +1735,14 @@
</span><span class="cx"> offset -= charOffset.offset;
</span><span class="cx"> domNode = previousNode(domNode);
</span><span class="cx"> if (domNode) {
</span><del>- charOffset = characterOffsetForNodeAndOffset(*domNode, 0, true);
</del><ins>+ charOffset = characterOffsetForNodeAndOffset(*domNode, 0, TraverseOptionToNodeEnd);
</ins><span class="cx"> } else
</span><span class="cx"> return CharacterOffset();
</span><span class="cx"> if (!offset)
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> if (offset > 0)
</span><del>- charOffset = characterOffsetForNodeAndOffset(*charOffset.node, charOffset.offset - offset, false);
</del><ins>+ charOffset = characterOffsetForNodeAndOffset(*charOffset.node, charOffset.offset - offset);
</ins><span class="cx"> return charOffset;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1750,14 +1762,30 @@
</span><span class="cx"> return characterOffset;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AXObjectCache::textMarkerDataForCharacterOffset(TextMarkerData& textMarkerData, Node& node, int offset, bool toNodeEnd, bool ignoreStart)
</del><ins>+void AXObjectCache::textMarkerDataForCharacterOffset(TextMarkerData& textMarkerData, const CharacterOffset& characterOffset)
</ins><span class="cx"> {
</span><span class="cx"> memset(&textMarkerData, 0, sizeof(TextMarkerData));
</span><del>-
- CharacterOffset characterOffset = characterOffsetForNodeAndOffset(node, offset, toNodeEnd, ignoreStart);
</del><span class="cx"> setTextMarkerDataWithCharacterOffset(textMarkerData, characterOffset);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void AXObjectCache::textMarkerDataForNextCharacterOffset(TextMarkerData& textMarkerData, const CharacterOffset& characterOffset)
+{
+ CharacterOffset next = characterOffset;
+ do {
+ next = nextCharacterOffset(next);
+ textMarkerDataForCharacterOffset(textMarkerData, next);
+ } while (textMarkerData.ignored);
+}
+
+void AXObjectCache::textMarkerDataForPreviousCharacterOffset(TextMarkerData& textMarkerData, const CharacterOffset& characterOffset)
+{
+ CharacterOffset previous = characterOffset;
+ do {
+ previous = previousCharacterOffset(previous);
+ textMarkerDataForCharacterOffset(textMarkerData, previous);
+ } while (textMarkerData.ignored);
+}
+
</ins><span class="cx"> Node* AXObjectCache::nextNode(Node* node) const
</span><span class="cx"> {
</span><span class="cx"> if (!node)
</span><span class="lines">@@ -1875,20 +1903,20 @@
</span><span class="cx"> cache->setNodeInUse(domNode);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-CharacterOffset AXObjectCache::nextCharacterOffset(const CharacterOffset& characterOffset)
</del><ins>+CharacterOffset AXObjectCache::nextCharacterOffset(const CharacterOffset& characterOffset, bool ignoreStart)
</ins><span class="cx"> {
</span><span class="cx"> if (characterOffset.isNull())
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><del>- return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset + 1);
</del><ins>+ return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset + 1, ignoreStart ? TraverseOptionDefault : TraverseOptionIncludeStart);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-CharacterOffset AXObjectCache::previousCharacterOffset(const CharacterOffset& characterOffset)
</del><ins>+CharacterOffset AXObjectCache::previousCharacterOffset(const CharacterOffset& characterOffset, bool ignoreStart)
</ins><span class="cx"> {
</span><span class="cx"> if (characterOffset.isNull())
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><del>- return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset - 1, false, false);
</del><ins>+ return characterOffsetForNodeAndOffset(*characterOffset.node, characterOffset.offset - 1, ignoreStart ? TraverseOptionDefault : TraverseOptionIncludeStart);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static unsigned startWordBoundary(StringView text, unsigned offset, BoundarySearchContextAvailability mayHaveMoreContext, bool& needMoreContext)
</span><span class="lines">@@ -1925,9 +1953,8 @@
</span><span class="cx">
</span><span class="cx"> CharacterOffset c = characterOffset;
</span><span class="cx"> if (side == RightWordIfOnBoundary) {
</span><del>- // FIXME: need to remove this when isEndOfParagraph is implemented for CharacterOffset.
- VisiblePosition vp = visiblePositionFromCharacterOffset(c);
- if (isEndOfParagraph(vp))
</del><ins>+ CharacterOffset endOfParagraph = endCharacterOffsetOfParagraph(c);
+ if (c.isEqual(endOfParagraph))
</ins><span class="cx"> return c;
</span><span class="cx">
</span><span class="cx"> c = nextCharacterOffset(characterOffset);
</span><span class="lines">@@ -1945,12 +1972,11 @@
</span><span class="cx">
</span><span class="cx"> CharacterOffset c = characterOffset;
</span><span class="cx"> if (side == LeftWordIfOnBoundary) {
</span><del>- // FIXME: need to remove this when isStartOfParagraph is implemented for CharacterOffset.
- VisiblePosition vp = visiblePositionFromCharacterOffset(c);
- if (isStartOfParagraph(vp))
</del><ins>+ CharacterOffset startOfParagraph = startCharacterOffsetOfParagraph(c);
+ if (c.isEqual(startOfParagraph))
</ins><span class="cx"> return c;
</span><span class="cx">
</span><del>- c = previousCharacterOffset(characterOffset);
</del><ins>+ c = previousCharacterOffset(characterOffset, false);
</ins><span class="cx"> if (c.isNull())
</span><span class="cx"> return characterOffset;
</span><span class="cx"> }
</span><span class="lines">@@ -1963,7 +1989,7 @@
</span><span class="cx"> if (characterOffset.isNull())
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><del>- CharacterOffset previousOffset = previousCharacterOffset(characterOffset);
</del><ins>+ CharacterOffset previousOffset = previousCharacterOffset(characterOffset, false);
</ins><span class="cx"> if (previousOffset.isNull())
</span><span class="cx"> return CharacterOffset();
</span><span class="cx">
</span><span class="lines">@@ -2111,13 +2137,84 @@
</span><span class="cx"> // The next variable contains a usable index into a text node
</span><span class="cx"> if (&node == characterOffset.node)
</span><span class="cx"> next -= characterOffset.startIndex;
</span><del>- return characterOffsetForNodeAndOffset(node, next, false);
</del><ins>+ return characterOffsetForNodeAndOffset(node, next, TraverseOptionIncludeStart);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> int characterCount = characterOffset.offset - (string.size() - suffixLength - next);
</span><del>- return characterOffsetForNodeAndOffset(*characterOffset.node, characterCount, false, false);
</del><ins>+ return characterOffsetForNodeAndOffset(*characterOffset.node, characterCount, TraverseOptionIncludeStart);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+CharacterOffset AXObjectCache::startCharacterOffsetOfParagraph(const CharacterOffset& characterOffset, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
+ if (characterOffset.isNull())
+ return CharacterOffset();
+
+ Node* startNode = characterOffset.node;
+
+ if (isRenderedAsNonInlineTableImageOrHR(startNode))
+ return startOrEndCharacterOffsetForRange(rangeForNodeContents(startNode), true);
+
+ Node* startBlock = enclosingBlock(startNode);
+ int offset = characterOffset.startIndex + characterOffset.offset;
+ Position p(startNode, offset, Position::PositionIsOffsetInAnchor);
+ Node* highestRoot = highestEditableRoot(p);
+ Position::AnchorType type = Position::PositionIsOffsetInAnchor;
+
+ Node* node = findStartOfParagraph(startNode, highestRoot, startBlock, offset, type, boundaryCrossingRule);
+
+ if (type == Position::PositionIsOffsetInAnchor)
+ return characterOffsetForNodeAndOffset(*node, offset, TraverseOptionIncludeStart);
+
+ return startOrEndCharacterOffsetForRange(rangeForNodeContents(node), true);
+}
+
+CharacterOffset AXObjectCache::endCharacterOffsetOfParagraph(const CharacterOffset& characterOffset, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
+ if (characterOffset.isNull())
+ return CharacterOffset();
+
+ Node* startNode = characterOffset.node;
+ if (isRenderedAsNonInlineTableImageOrHR(startNode))
+ return startOrEndCharacterOffsetForRange(rangeForNodeContents(startNode), false);
+
+ Node* stayInsideBlock = enclosingBlock(startNode);
+ int offset = characterOffset.startIndex + characterOffset.offset;
+ Position p(startNode, offset, Position::PositionIsOffsetInAnchor);
+ Node* highestRoot = highestEditableRoot(p);
+ Position::AnchorType type = Position::PositionIsOffsetInAnchor;
+
+ Node* node = findEndOfParagraph(startNode, highestRoot, stayInsideBlock, offset, type, boundaryCrossingRule);
+ if (type == Position::PositionIsOffsetInAnchor) {
+ if (node->isTextNode()) {
+ CharacterOffset startOffset = startOrEndCharacterOffsetForRange(rangeForNodeContents(node), true);
+ offset -= startOffset.startIndex;
+ }
+ return characterOffsetForNodeAndOffset(*node, offset, TraverseOptionIncludeStart);
+ }
+
+ return startOrEndCharacterOffsetForRange(rangeForNodeContents(node), false);
+}
+
+RefPtr<Range> AXObjectCache::paragraphForCharacterOffset(const CharacterOffset& characterOffset)
+{
+ CharacterOffset start = startCharacterOffsetOfParagraph(characterOffset);
+ CharacterOffset end = endCharacterOffsetOfParagraph(characterOffset);
+
+ return rangeForUnorderedCharacterOffsets(start, end);
+}
+
+CharacterOffset AXObjectCache::nextParagraphEndCharacterOffset(const CharacterOffset& characterOffset)
+{
+ // make sure we move off of a paragraph end
+ return endCharacterOffsetOfParagraph(nextCharacterOffset(characterOffset));
+}
+
+CharacterOffset AXObjectCache::previousParagraphStartCharacterOffset(const CharacterOffset& characterOffset)
+{
+ // make sure we move off of a paragraph start
+ return startCharacterOffsetOfParagraph(previousCharacterOffset(characterOffset, false));
+}
+
</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 (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -74,6 +74,12 @@
</span><span class="cx">
</span><span class="cx"> int remaining() const { return remainingOffset; }
</span><span class="cx"> bool isNull() const { return !node; }
</span><ins>+ bool isEqual(CharacterOffset& other) const
+ {
+ if (isNull() || other.isNull())
+ return false;
+ return node == other.node && startIndex == other.startIndex && offset == other.offset;
+ }
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> class AXComputedObjectAttributeCache {
</span><span class="lines">@@ -185,9 +191,13 @@
</span><span class="cx">
</span><span class="cx"> // Text marker utilities.
</span><span class="cx"> void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
</span><ins>+ void textMarkerDataForCharacterOffset(TextMarkerData&, const CharacterOffset&);
+ void textMarkerDataForNextCharacterOffset(TextMarkerData&, const CharacterOffset&);
+ void textMarkerDataForPreviousCharacterOffset(TextMarkerData&, const CharacterOffset&);
</ins><span class="cx"> VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
</span><span class="cx"> CharacterOffset characterOffsetForTextMarkerData(TextMarkerData&);
</span><del>- void textMarkerDataForCharacterOffset(TextMarkerData&, Node&, int, bool toNodeEnd = false, bool ignoreStart = true);
</del><ins>+ CharacterOffset nextCharacterOffset(const CharacterOffset&, bool ignoreStart = true);
+ CharacterOffset previousCharacterOffset(const CharacterOffset&, bool ignoreStart = true);
</ins><span class="cx"> void startOrEndTextMarkerDataForRange(TextMarkerData&, RefPtr<Range>, bool);
</span><span class="cx"> AccessibilityObject* accessibilityObjectForTextMarkerData(TextMarkerData&);
</span><span class="cx"> RefPtr<Range> rangeForUnorderedCharacterOffsets(const CharacterOffset&, const CharacterOffset&);
</span><span class="lines">@@ -195,12 +205,15 @@
</span><span class="cx"> static int lengthForRange(Range*);
</span><span class="cx">
</span><span class="cx"> // Word boundary
</span><del>- CharacterOffset startCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
- CharacterOffset endCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
</del><span class="cx"> CharacterOffset nextWordEndCharacterOffset(const CharacterOffset&);
</span><span class="cx"> CharacterOffset previousWordStartCharacterOffset(const CharacterOffset&);
</span><span class="cx"> RefPtr<Range> leftWordRange(const CharacterOffset&);
</span><span class="cx"> RefPtr<Range> rightWordRange(const CharacterOffset&);
</span><ins>+
+ // Paragraph
+ RefPtr<Range> paragraphForCharacterOffset(const CharacterOffset&);
+ CharacterOffset nextParagraphEndCharacterOffset(const CharacterOffset&);
+ CharacterOffset previousParagraphStartCharacterOffset(const CharacterOffset&);
</ins><span class="cx">
</span><span class="cx"> enum AXNotification {
</span><span class="cx"> AXActiveDescendantChanged,
</span><span class="lines">@@ -293,6 +306,7 @@
</span><span class="cx"> bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
</span><span class="cx">
</span><span class="cx"> // CharacterOffset functions.
</span><ins>+ enum TraverseOption { TraverseOptionDefault = 1 << 0, TraverseOptionToNodeEnd = 1 << 1, TraverseOptionIncludeStart = 1 << 2 };
</ins><span class="cx"> Node* nextNode(Node*) const;
</span><span class="cx"> Node* previousNode(Node*) const;
</span><span class="cx"> CharacterOffset traverseToOffsetInRange(RefPtr<Range>, int, bool, bool stayWithinRange = false);
</span><span class="lines">@@ -302,11 +316,13 @@
</span><span class="cx"> UChar32 characterAfter(const CharacterOffset&);
</span><span class="cx"> UChar32 characterBefore(const CharacterOffset&);
</span><span class="cx"> CharacterOffset startOrEndCharacterOffsetForRange(RefPtr<Range>, bool);
</span><del>- CharacterOffset characterOffsetForNodeAndOffset(Node&, int, bool toNodeEnd = false, bool ignoreStart = true);
- CharacterOffset nextCharacterOffset(const CharacterOffset&);
- CharacterOffset previousCharacterOffset(const CharacterOffset&);
</del><ins>+ CharacterOffset characterOffsetForNodeAndOffset(Node&, int, TraverseOption = TraverseOptionDefault);
</ins><span class="cx"> CharacterOffset previousWordBoundary(CharacterOffset&, BoundarySearchFunction);
</span><span class="cx"> CharacterOffset nextWordBoundary(CharacterOffset&, BoundarySearchFunction);
</span><ins>+ CharacterOffset startCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
+ CharacterOffset endCharacterOffsetOfWord(const CharacterOffset&, EWordSide = RightWordIfOnBoundary);
+ CharacterOffset startCharacterOffsetOfParagraph(const CharacterOffset&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
+ CharacterOffset endCharacterOffsetOfParagraph(const CharacterOffset&, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> AccessibilityObject* rootWebArea();
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityiosWebAccessibilityObjectWrapperIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -189,7 +189,7 @@
</span><span class="cx"> return nil;
</span><span class="cx">
</span><span class="cx"> TextMarkerData textMarkerData;
</span><del>- cache->textMarkerDataForCharacterOffset(textMarkerData, *characterOffset.node, characterOffset.offset, false);
</del><ins>+ cache->textMarkerDataForCharacterOffset(textMarkerData, characterOffset);
</ins><span class="cx"> if (!textMarkerData.axID && !textMarkerData.ignored)
</span><span class="cx"> return nil;
</span><span class="cx"> return [[[WebAccessibilityTextMarker alloc] initWithTextMarker:&textMarkerData cache:cache] autorelease];
</span><span class="lines">@@ -2425,20 +2425,28 @@
</span><span class="cx">
</span><span class="cx"> - (WebAccessibilityTextMarker *)nextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</span><span class="cx"> {
</span><del>- characterOffset.offset = characterOffset.offset + 1;
- WebAccessibilityTextMarker *textMarker = [WebAccessibilityTextMarker textMarkerWithCharacterOffset:characterOffset cache:m_object->axObjectCache()];
- if (textMarker && textMarker.isIgnored)
- textMarker = [self nextMarkerForCharacterOffset:characterOffset];
- return textMarker;
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+
+ TextMarkerData textMarkerData;
+ cache->textMarkerDataForNextCharacterOffset(textMarkerData, characterOffset);
+ if (!textMarkerData.axID)
+ return nil;
+ return [[[WebAccessibilityTextMarker alloc] initWithTextMarker:&textMarkerData cache:cache] autorelease];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (WebAccessibilityTextMarker *)previousMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</span><span class="cx"> {
</span><del>- characterOffset.offset = characterOffset.offset - 1;
- WebAccessibilityTextMarker *textMarker = [WebAccessibilityTextMarker textMarkerWithCharacterOffset:characterOffset cache:m_object->axObjectCache()];
- if (textMarker && textMarker.isIgnored)
- textMarker = [self previousMarkerForCharacterOffset:characterOffset];
- return textMarker;
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+
+ TextMarkerData textMarkerData;
+ cache->textMarkerDataForPreviousCharacterOffset(textMarkerData, characterOffset);
+ if (!textMarkerData.axID)
+ return nil;
+ return [[[WebAccessibilityTextMarker alloc] initWithTextMarker:&textMarkerData cache:cache] autorelease];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> - (RefPtr<Range>)rangeForTextMarkers:(NSArray *)textMarkers
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilitymacWebAccessibilityObjectWrapperMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -840,45 +840,52 @@
</span><span class="cx"> return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-- (id)nextTextMarkerForNode:(Node&)node offset:(int)offset
</del><ins>+static id nextTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
</ins><span class="cx"> {
</span><del>- int nextOffset = offset + 1;
- id textMarker = [self textMarkerForNode:node offset:nextOffset];
- if (isTextMarkerIgnored(textMarker))
- textMarker = [self nextTextMarkerForNode:node offset:nextOffset];
- return textMarker;
</del><ins>+ if (!cache)
+ return nil;
+
+ TextMarkerData textMarkerData;
+ cache->textMarkerDataForNextCharacterOffset(textMarkerData, characterOffset);
+ if (!textMarkerData.axID)
+ return nil;
+ return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-- (id)previousTextMarkerForNode:(Node&)node offset:(int)offset
</del><ins>+static id previousTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
</ins><span class="cx"> {
</span><del>- int previousOffset = offset - 1;
- id textMarker = [self textMarkerForNode:node offset:previousOffset];
- if (isTextMarkerIgnored(textMarker))
- textMarker = [self previousTextMarkerForNode:node offset:previousOffset];
- return textMarker;
</del><ins>+ if (!cache)
+ return nil;
+
+ TextMarkerData textMarkerData;
+ cache->textMarkerDataForPreviousCharacterOffset(textMarkerData, characterOffset);
+ if (!textMarkerData.axID)
+ return nil;
+ return CFBridgingRelease(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-- (id)textMarkerForNode:(Node&)node offset:(int)offset ignoreStart:(BOOL)ignoreStart
</del><ins>+- (id)nextTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</ins><span class="cx"> {
</span><del>- return textMarkerForCharacterOffset(m_object->axObjectCache(), node, offset, false, ignoreStart);
</del><ins>+ return nextTextMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-- (id)textMarkerForNode:(Node&)node offset:(int)offset
</del><ins>+- (id)previousTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</ins><span class="cx"> {
</span><del>- return [self textMarkerForNode:node offset:offset ignoreStart:YES];
</del><ins>+ return previousTextMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-static id textMarkerForCharacterOffset(AXObjectCache* cache, Node& node, int offset, bool toNodeEnd, bool ignoreStart)
</del><ins>+- (id)textMarkerForCharacterOffset:(CharacterOffset&)characterOffset
</ins><span class="cx"> {
</span><ins>+ return textMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
+}
+
+static id textMarkerForCharacterOffset(AXObjectCache* cache, const CharacterOffset& characterOffset)
+{
</ins><span class="cx"> if (!cache)
</span><span class="cx"> return nil;
</span><span class="cx">
</span><del>- Node* domNode = &node;
- if (!domNode)
- return nil;
-
</del><span class="cx"> TextMarkerData textMarkerData;
</span><del>- cache->textMarkerDataForCharacterOffset(textMarkerData, node, offset, toNodeEnd, ignoreStart);
</del><ins>+ cache->textMarkerDataForCharacterOffset(textMarkerData, characterOffset);
</ins><span class="cx"> if (!textMarkerData.axID && !textMarkerData.ignored)
</span><span class="cx"> return nil;
</span><span class="cx">
</span><span class="lines">@@ -4066,12 +4073,12 @@
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
</span><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><del>- return [self nextTextMarkerForNode:*characterOffset.node offset:characterOffset.offset];
</del><ins>+ return [self nextTextMarkerForCharacterOffset:characterOffset];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
</span><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><del>- return [self previousTextMarkerForNode:*characterOffset.node offset:characterOffset.offset];
</del><ins>+ return [self previousTextMarkerForCharacterOffset:characterOffset];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
</span><span class="lines">@@ -4111,9 +4118,12 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
</span><del>- VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
- VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
- return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+ CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+ RefPtr<Range> range = cache->paragraphForCharacterOffset(characterOffset);
+ return [self textMarkerRangeFromRange:range];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
</span><span class="lines">@@ -4122,7 +4132,7 @@
</span><span class="cx"> return nil;
</span><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset nextEnd = cache->nextWordEndCharacterOffset(characterOffset);
</span><del>- return [self textMarkerForNode:*nextEnd.node offset:nextEnd.offset];
</del><ins>+ return [self textMarkerForCharacterOffset:nextEnd];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
</span><span class="lines">@@ -4131,7 +4141,7 @@
</span><span class="cx"> return nil;
</span><span class="cx"> CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
</span><span class="cx"> CharacterOffset previousStart = cache->previousWordStartCharacterOffset(characterOffset);
</span><del>- return [self textMarkerForNode:*previousStart.node offset:previousStart.offset ignoreStart:NO];
</del><ins>+ return [self textMarkerForCharacterOffset:previousStart];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
</span><span class="lines">@@ -4160,8 +4170,12 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
</span><del>- VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
- return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];
</del><ins>+ AXObjectCache* cache = m_object->axObjectCache();
+ if (!cache)
+ return nil;
+ CharacterOffset characterOffset = [self characterOffsetForTextMarker:textMarker];
+ CharacterOffset previousStart = cache->previousParagraphStartCharacterOffset(characterOffset);
+ return [self textMarkerForCharacterOffset:previousStart];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.cpp (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/editing/VisibleUnits.cpp        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1142,24 +1142,9 @@
</span><span class="cx"> return position.honorEditingBoundaryAtOrAfter(nextBoundary(position, nextSentencePositionBoundary));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
</del><ins>+Node* findStartOfParagraph(Node* startNode, Node* highestRoot, Node* startBlock, int& offset, Position::AnchorType& type, EditingBoundaryCrossingRule boundaryCrossingRule)
</ins><span class="cx"> {
</span><del>- Position p = c.deepEquivalent();
- Node* startNode = p.deprecatedNode();
-
- if (!startNode)
- return VisiblePosition();
-
- if (isRenderedAsNonInlineTableImageOrHR(startNode))
- return positionBeforeNode(startNode);
-
- Node* startBlock = enclosingBlock(startNode);
-
</del><span class="cx"> Node* node = startNode;
</span><del>- Node* highestRoot = highestEditableRoot(p);
- int offset = p.deprecatedEditingOffset();
- Position::AnchorType type = p.anchorType();
-
</del><span class="cx"> Node* n = startNode;
</span><span class="cx"> while (n) {
</span><span class="cx"> #if ENABLE(USERSELECT_ALL)
</span><span class="lines">@@ -1198,8 +1183,10 @@
</span><span class="cx"> if (n == startNode && o < i)
</span><span class="cx"> i = std::max(0, o);
</span><span class="cx"> while (--i >= 0) {
</span><del>- if (text[i] == '\n')
- return VisiblePosition(Position(downcast<Text>(n), i + 1), DOWNSTREAM);
</del><ins>+ if (text[i] == '\n') {
+ offset = i + 1;
+ return n;
+ }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> node = n;
</span><span class="lines">@@ -1213,33 +1200,12 @@
</span><span class="cx"> n = NodeTraversal::previousPostOrder(*n, startBlock);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (type == Position::PositionIsOffsetInAnchor) {
- ASSERT(type == Position::PositionIsOffsetInAnchor || !offset);
- return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
- }
-
- return VisiblePosition(Position(node, type), DOWNSTREAM);
</del><ins>+ return node;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
-{
- if (c.isNull())
- return VisiblePosition();
-
- Position p = c.deepEquivalent();
- Node* startNode = p.deprecatedNode();
-
- if (isRenderedAsNonInlineTableImageOrHR(startNode))
- return positionAfterNode(startNode);
-
- Node* startBlock = enclosingBlock(startNode);
- Node* stayInsideBlock = startBlock;
-
</del><ins>+Node* findEndOfParagraph(Node* startNode, Node* highestRoot, Node* stayInsideBlock, int& offset, Position::AnchorType& type, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
</ins><span class="cx"> Node* node = startNode;
</span><del>- Node* highestRoot = highestEditableRoot(p);
- int offset = p.deprecatedEditingOffset();
- Position::AnchorType type = p.anchorType();
-
</del><span class="cx"> Node* n = startNode;
</span><span class="cx"> while (n) {
</span><span class="cx"> #if ENABLE(USERSELECT_ALL)
</span><span class="lines">@@ -1279,8 +1245,10 @@
</span><span class="cx"> int o = n == startNode ? offset : 0;
</span><span class="cx"> int length = text.length();
</span><span class="cx"> for (int i = o; i < length; ++i) {
</span><del>- if (text[i] == '\n')
- return VisiblePosition(Position(downcast<Text>(n), i), DOWNSTREAM);
</del><ins>+ if (text[i] == '\n') {
+ offset = i;
+ return n;
+ }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> node = n;
</span><span class="lines">@@ -1293,7 +1261,62 @@
</span><span class="cx"> } else
</span><span class="cx"> n = NodeTraversal::next(*n, stayInsideBlock);
</span><span class="cx"> }
</span><ins>+ return node;
+}
</ins><span class="cx">
</span><ins>+VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
+ Position p = c.deepEquivalent();
+ Node* startNode = p.deprecatedNode();
+
+ if (!startNode)
+ return VisiblePosition();
+
+ if (isRenderedAsNonInlineTableImageOrHR(startNode))
+ return positionBeforeNode(startNode);
+
+ Node* startBlock = enclosingBlock(startNode);
+
+ Node* highestRoot = highestEditableRoot(p);
+ int offset = p.deprecatedEditingOffset();
+ Position::AnchorType type = p.anchorType();
+
+ Node* node = findStartOfParagraph(startNode, highestRoot, startBlock, offset, type, boundaryCrossingRule);
+
+ if (is<Text>(node))
+ return VisiblePosition(Position(downcast<Text>(node), offset), DOWNSTREAM);
+
+ if (type == Position::PositionIsOffsetInAnchor) {
+ ASSERT(type == Position::PositionIsOffsetInAnchor || !offset);
+ return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
+ }
+
+ return VisiblePosition(Position(node, type), DOWNSTREAM);
+}
+
+VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
+{
+ if (c.isNull())
+ return VisiblePosition();
+
+ Position p = c.deepEquivalent();
+ Node* startNode = p.deprecatedNode();
+
+ if (isRenderedAsNonInlineTableImageOrHR(startNode))
+ return positionAfterNode(startNode);
+
+ Node* startBlock = enclosingBlock(startNode);
+ Node* stayInsideBlock = startBlock;
+
+ Node* highestRoot = highestEditableRoot(p);
+ int offset = p.deprecatedEditingOffset();
+ Position::AnchorType type = p.anchorType();
+
+ Node* node = findEndOfParagraph(startNode, highestRoot, stayInsideBlock, offset, type, boundaryCrossingRule);
+
+ if (is<Text>(node))
+ return VisiblePosition(Position(downcast<Text>(node), offset), DOWNSTREAM);
+
</ins><span class="cx"> if (type == Position::PositionIsOffsetInAnchor)
</span><span class="cx"> return VisiblePosition(Position(node, offset, type), DOWNSTREAM);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.h (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Source/WebCore/editing/VisibleUnits.h        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -116,6 +116,8 @@
</span><span class="cx"> unsigned prefixLengthForRange(RefPtr<Range>, Vector<UChar, 1024>&);
</span><span class="cx"> unsigned backwardSearchForBoundaryWithTextIterator(SimplifiedBackwardsTextIterator&, Vector<UChar, 1024>&, unsigned, BoundarySearchFunction);
</span><span class="cx"> unsigned forwardSearchForBoundaryWithTextIterator(TextIterator&, Vector<UChar, 1024>&, unsigned, BoundarySearchFunction);
</span><ins>+Node* findStartOfParagraph(Node*, Node*, Node*, int&, Position::AnchorType&, EditingBoundaryCrossingRule);
+Node* findEndOfParagraph(Node*, Node*, Node*, int&, Position::AnchorType&, EditingBoundaryCrossingRule);
</ins><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/ChangeLog        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2016-02-12 Nan Wang <n_wang@apple.com>
+
+ AX: Implement paragraph related text marker functions using TextIterator
+ https://bugs.webkit.org/show_bug.cgi?id=154098
+ <rdar://problem/24269675>
+
+ Reviewed by Chris Fleizach.
+
+ * DumpRenderTree/AccessibilityUIElement.cpp:
+ (nextWordEndTextMarkerForTextMarkerCallback):
+ (paragraphTextMarkerRangeForTextMarkerCallback):
+ (previousParagraphStartTextMarkerForTextMarkerCallback):
+ (nextParagraphEndTextMarkerForTextMarkerCallback):
+ (setSelectedVisibleTextRangeCallback):
+ (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ (AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ (AccessibilityUIElement::getJSClass):
+ * DumpRenderTree/AccessibilityUIElement.h:
+ * DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
+ (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ (AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+ (AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ (AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ (AccessibilityUIElement::supportedActions):
+ * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp:
+ (WTR::AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker):
+ (WTR::AccessibilityUIElement::previousWordStartTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+ * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+ * WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
+ (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::mathPostscriptsDescription):
+ * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+ (WTR::AccessibilityUIElement::nextWordEndTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker):
+ (WTR::AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker):
+ (WTR::AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker):
+ (WTR::_convertMathMultiscriptPairsToString):
+
</ins><span class="cx"> 2016-02-12 Jason Marcell <jmarcell@apple.com>
</span><span class="cx">
</span><span class="cx"> Open source bot watcher's dashboard fails assertion in BuildbotQueue.prototype.compareIterationsByRevisions
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeAccessibilityUIElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1010,6 +1010,33 @@
</span><span class="cx"> return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextWordEndTextMarkerForTextMarker(marker));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static JSValueRef paragraphTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->paragraphTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef previousParagraphStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousParagraphStartTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef nextParagraphEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextParagraphEndTextMarkerForTextMarker(marker));
+}
+
</ins><span class="cx"> static JSValueRef setSelectedVisibleTextRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
</span><span class="cx"> {
</span><span class="cx"> AccessibilityUIElement* uiElement = toAXElement(thisObject);
</span><span class="lines">@@ -1620,6 +1647,21 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
</ins><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> // Destruction
</span><span class="lines">@@ -1804,6 +1846,9 @@
</span><span class="cx"> { "rightWordTextMarkerRangeForTextMarker", rightWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx"> { "previousWordStartTextMarkerForTextMarker", previousWordStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx"> { "nextWordEndTextMarkerForTextMarker", nextWordEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><ins>+ { "paragraphTextMarkerRangeForTextMarker", paragraphTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "previousParagraphStartTextMarkerForTextMarker", previousParagraphStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "nextParagraphEndTextMarkerForTextMarker", nextParagraphEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</ins><span class="cx"> { "setSelectedChild", setSelectedChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx"> { "setSelectedChildAtIndex", setSelectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span><span class="cx"> { "removeSelectionAtIndex", removeSelectionAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeAccessibilityUIElementh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.h (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.h        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.h        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -264,6 +264,9 @@
</span><span class="cx"> AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
</span><span class="cx"> AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
</span><span class="cx"> AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
</span><ins>+ AccessibilityTextMarkerRange paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*);
</ins><span class="cx"> AccessibilityTextMarkerRange selectedTextMarkerRange();
</span><span class="cx"> void resetSelectedTextMarkerRange();
</span><span class="cx"> bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreeiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -570,6 +570,21 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
</ins><span class="cx"> #endif // SUPPORTS_AX_TEXTMARKERS && PLATFORM(IOS)
</span><span class="cx">
</span><span class="cx"> #pragma mark Unused
</span></span></pre></div>
<a id="trunkToolsDumpRenderTreemacAccessibilityUIElementMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1886,6 +1886,36 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id textMarkerRange = [m_element accessibilityAttributeValue:@"AXParagraphTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarkerRange(textMarkerRange);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id previousTextMarker = [m_element accessibilityAttributeValue:@"AXPreviousParagraphStartTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarker(previousTextMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id nextTextMarker = [m_element accessibilityAttributeValue:@"AXNextParagraphEndTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarker(nextTextMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
</ins><span class="cx"> #endif // SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC)
</span><span class="cx">
</span><span class="cx"> JSStringRef AccessibilityUIElement::supportedActions()
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -249,6 +249,9 @@
</span><span class="cx"> PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
</span><span class="cx"> PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
</span><span class="cx"> PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
</span><ins>+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
</ins><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> } // namespace WTR
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleAccessibilityUIElementh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -255,6 +255,9 @@
</span><span class="cx"> PassRefPtr<AccessibilityTextMarkerRange> rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
</span><span class="cx"> PassRefPtr<AccessibilityTextMarker> previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
</span><span class="cx"> PassRefPtr<AccessibilityTextMarker> nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
</span><ins>+ PassRefPtr<AccessibilityTextMarkerRange> paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*);
</ins><span class="cx">
</span><span class="cx"> // Returns an ordered list of supported actions for an element.
</span><span class="cx"> JSRetainPtr<JSStringRef> supportedActions() const;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleBindingsAccessibilityUIElementidl"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -205,6 +205,9 @@
</span><span class="cx"> AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker);
</span><span class="cx"> AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
</span><span class="cx"> AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
</span><ins>+ AccessibilityTextMarkerRange paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker);
+ AccessibilityTextMarker previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
+ AccessibilityTextMarker nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker);
</ins><span class="cx">
</span><span class="cx"> // Returns an ordered list of supported actions for an element.
</span><span class="cx"> readonly attribute DOMString supportedActions;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleiosAccessibilityUIElementIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1116,6 +1116,21 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ return nullptr;
+}
+
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ return nullptr;
+}
+
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ return nullptr;
+}
+
</ins><span class="cx"> JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
</span><span class="cx"> {
</span><span class="cx"> return 0;
</span></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundlemacAccessibilityUIElementMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (196545 => 196546)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm        2016-02-13 04:52:01 UTC (rev 196545)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm        2016-02-13 05:24:24 UTC (rev 196546)
</span><span class="lines">@@ -1913,6 +1913,36 @@
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id textMarkerRange = [m_element accessibilityAttributeValue:@"AXParagraphTextMarkerRangeForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarkerRange::create(textMarkerRange);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id previousParagraphStartMarker = [m_element accessibilityAttributeValue:@"AXPreviousParagraphStartTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarker::create(previousParagraphStartMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ id nextParagraphEndMarker = [m_element accessibilityAttributeValue:@"AXNextParagraphEndTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
+ return AccessibilityTextMarker::create(nextParagraphEndMarker);
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+
</ins><span class="cx"> static NSString *_convertMathMultiscriptPairsToString(NSArray *pairs)
</span><span class="cx"> {
</span><span class="cx"> __block NSMutableString *result = [NSMutableString string];
</span></span></pre>
</div>
</div>
</body>
</html>