<!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>[190363] trunk/Source</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/190363">190363</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2015-09-30 12:36:37 -0700 (Wed, 30 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Compute document marker rects at use time instead of paint time
https://bugs.webkit.org/show_bug.cgi?id=149643

Reviewed by Darin Adler.

* dom/DocumentMarkerController.cpp:
(WebCore::DocumentMarkerController::DocumentMarkerController):
(WebCore::DocumentMarkerController::detach):
Store and zero the Document backpointer.

(WebCore::DocumentMarkerController::addMarker):
(WebCore::DocumentMarkerController::addTextMatchMarker):
(WebCore::DocumentMarkerController::addDictationPhraseWithAlternativesMarker):
(WebCore::DocumentMarkerController::addDictationResultMarker):
(WebCore::DocumentMarkerController::copyMarkers):
Remove some useless comments.

(WebCore::updateRenderedRectsForMarker):
Use Range to compute the (unclipped, absolute) text rects, and store them
on the RenderedDocumentMarker.

(WebCore::DocumentMarkerController::invalidateRectsForAllMarkers):
(WebCore::DocumentMarkerController::invalidateRectsForMarkersInNode):
Mark the relevant markers' rects as invalid, and notify the ChromeClient.

(WebCore::DocumentMarkerController::updateRectsForInvalidatedMarkersOfType):
Run through all markers, computing rects for ones that don't have valid rects.
We will do layout (once) if necessary. However, this is most commonly
called from a place where layout should already be up to date, so this
should not happen often. updateRenderedRectsForMarker also asserts
that layout is up to date.

(WebCore::DocumentMarkerController::renderedRectsForMarkers):
Retrieve all markers of the given type, clip them by overflow clip and
frame clip, and return them to the caller.

(WebCore::DocumentMarkerController::addMarker):
(WebCore::DocumentMarkerController::markerContainingPoint):
(WebCore::DocumentMarkerController::markersFor):
(WebCore::DocumentMarkerController::repaintMarkers):
(WebCore::DocumentMarkerController::shiftMarkers):
(DocumentMarkerController::setMarkersActive):
(DocumentMarkerController::hasMarkers):
Modern iteration.

(WebCore::DocumentMarkerController::invalidateRenderedRectsForMarkersInRect): Deleted.
* dom/DocumentMarkerController.h:

* dom/Document.cpp:
(WebCore::Document::Document):
Pass the Document to the DocumentMarkerController.

* dom/RenderedDocumentMarker.h:
(WebCore::RenderedDocumentMarker::contains):
(WebCore::RenderedDocumentMarker::setUnclippedAbsoluteRects):
(WebCore::RenderedDocumentMarker::unclippedAbsoluteRects):
(WebCore::RenderedDocumentMarker::invalidate):
(WebCore::RenderedDocumentMarker::isValid):
(WebCore::RenderedDocumentMarker::addRenderedRect): Deleted.
(WebCore::RenderedDocumentMarker::renderedRects): Deleted.
Instead of keeping &quot;rendered&quot; rects, keep unclipped rects in absolute
document coordinates. Invalidation will happen wholesale instead of
based on dirty rects, because computation no longer happens at paint
time, so it's safe to throw all of the rects away.
Keep track of whether we have valid rects or not.

* editing/Editor.cpp:
(WebCore::Editor::countMatchesForText):
We don't need to do a fake whole-document paint just to compute the
document marker rects. They are computed on demand, using layout information
instead of paint-time information.

* page/ChromeClient.h:
Remove an unnecessary semicolon.
Add didInvalidateDocumentMarkerRects, which DocumentMarkerController
will call whenever document marker rects are invalidated (and when e.g.
the find holes PageOverlay should repaint itself).

* page/FrameView.cpp:
(WebCore::FrameView::layout):
Invalidate document marker's layout-computed rects after layout is complete.
They'll be lazily recomputed when next requested.

(WebCore::FrameView::willPaintContents):
Remove the pre-painting invalidation of document marker rects.

* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::paintTextMatchMarker):
(WebCore::InlineTextBox::paintDocumentMarker): Deleted.
(WebCore::InlineTextBox::computeRectForReplacementMarker): Deleted.
(WebCore::InlineTextBox::paintDocumentMarkers): Deleted.
Don't bother computing rendered rects for document markers at paint time.
Just do the actual painting work (which, for replacement markers, is
nothing at all).

* rendering/InlineTextBox.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateLayerPositions):
(WebCore::RenderLayer::updateLayerPositionsAfterScroll):
When RenderLayers move, invalidate document marker rects.

* rendering/svg/SVGInlineFlowBox.cpp:
(WebCore::SVGInlineFlowBox::paint):
(WebCore::SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer): Deleted.
* rendering/svg/SVGInlineFlowBox.h:
* rendering/svg/SVGRootInlineBox.cpp:
(WebCore::SVGRootInlineBox::paint):
Don't bother computing rendered rects for document markers at paint time.

* testing/Internals.cpp:
(WebCore::markerTypeFrom):
(WebCore::markerTypesFrom):
Add markerTypeFrom, which returns MarkerType enum values for the input string
instead of a MarkerTypes class.

(WebCore::Internals::dumpMarkerRects):
Dump all markers for the given type, and request them from DocumentMarkerController
instead of from the RenderedDocumentMarker, because we want fully clipped
rects, which can only be obtained from DocumentMarkerController.

* editing/FrameSelection.cpp:
(WebCore::FrameSelection::getTextRectangles):
Avoid enclosing unnecessarily, to avoid inflating zero-width text rects
to have a non-zero width. Callers appear to be OK with non-integral positions.

* testing/Internals.h:
* testing/Internals.idl:

* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::didInvalidateDocumentMarkerRects):
* WebProcess/WebCoreSupport/WebChromeClient.h:
Plumb the notification about invalidated document marker rects through to FindController.

* WebProcess/WebPage/FindController.cpp:
(WebKit::FindController::updateFindUIAfterPageScroll):
Make a document-relative PageOverlay, so that we get fast scrolling.

(WebKit::FindController::rectsForTextMatchesInRect):
Return find hole rects in main-FrameView content coordinates, to 
match the document-relative page overlay.
We'll only return rects that intersect the passed-in rect, which
comes from the dirty rect passed to drawRect.

(WebKit::FindController::drawRect):
Inflate the dirty rect by the border width so that we hit all relevant
markers in each tile. Otherwise, we would end up missing the border of a marker
that touched the edge of a tile.

(WebKit::FindController::didInvalidateDocumentMarkerRects):
Repaint (for now, the entire overlay) when document marker rects change.

* WebProcess/WebPage/FindController.h:

* WebView/WebHTMLView.mm:
(-[WebHTMLView rectsForTextMatches]):

* WebView.cpp:
(WebView::rectsForTextMatches):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentMarkerControllercpp">trunk/Source/WebCore/dom/DocumentMarkerController.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentMarkerControllerh">trunk/Source/WebCore/dom/DocumentMarkerController.h</a></li>
<li><a href="#trunkSourceWebCoredomRenderedDocumentMarkerh">trunk/Source/WebCore/dom/RenderedDocumentMarker.h</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorcpp">trunk/Source/WebCore/editing/Editor.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingFrameSelectioncpp">trunk/Source/WebCore/editing/FrameSelection.cpp</a></li>
<li><a href="#trunkSourceWebCorepageChromeClienth">trunk/Source/WebCore/page/ChromeClient.h</a></li>
<li><a href="#trunkSourceWebCorepageFrameViewcpp">trunk/Source/WebCore/page/FrameView.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingInlineTextBoxcpp">trunk/Source/WebCore/rendering/InlineTextBox.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingInlineTextBoxh">trunk/Source/WebCore/rendering/InlineTextBox.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayercpp">trunk/Source/WebCore/rendering/RenderLayer.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGInlineFlowBoxcpp">trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGInlineFlowBoxh">trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.h</a></li>
<li><a href="#trunkSourceWebCorerenderingsvgSVGRootInlineBoxcpp">trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebHTMLViewmm">trunk/Source/WebKit/mac/WebView/WebHTMLView.mm</a></li>
<li><a href="#trunkSourceWebKitwinChangeLog">trunk/Source/WebKit/win/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitwinWebViewcpp">trunk/Source/WebKit/win/WebView.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClientcpp">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClienth">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageFindControllercpp">trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageFindControllerh">trunk/Source/WebKit2/WebProcess/WebPage/FindController.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/ChangeLog        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1,3 +1,133 @@
</span><ins>+2015-09-30  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
+        Compute document marker rects at use time instead of paint time
+        https://bugs.webkit.org/show_bug.cgi?id=149643
+
+        Reviewed by Darin Adler.
+
+        * dom/DocumentMarkerController.cpp:
+        (WebCore::DocumentMarkerController::DocumentMarkerController):
+        (WebCore::DocumentMarkerController::detach):
+        Store and zero the Document backpointer.
+
+        (WebCore::DocumentMarkerController::addMarker):
+        (WebCore::DocumentMarkerController::addTextMatchMarker):
+        (WebCore::DocumentMarkerController::addDictationPhraseWithAlternativesMarker):
+        (WebCore::DocumentMarkerController::addDictationResultMarker):
+        (WebCore::DocumentMarkerController::copyMarkers):
+        Remove some useless comments.
+
+        (WebCore::updateRenderedRectsForMarker):
+        Use Range to compute the (unclipped, absolute) text rects, and store them
+        on the RenderedDocumentMarker.
+
+        (WebCore::DocumentMarkerController::invalidateRectsForAllMarkers):
+        (WebCore::DocumentMarkerController::invalidateRectsForMarkersInNode):
+        Mark the relevant markers' rects as invalid, and notify the ChromeClient.
+
+        (WebCore::DocumentMarkerController::updateRectsForInvalidatedMarkersOfType):
+        Run through all markers, computing rects for ones that don't have valid rects.
+        We will do layout (once) if necessary. However, this is most commonly
+        called from a place where layout should already be up to date, so this
+        should not happen often. updateRenderedRectsForMarker also asserts
+        that layout is up to date.
+
+        (WebCore::DocumentMarkerController::renderedRectsForMarkers):
+        Retrieve all markers of the given type, clip them by overflow clip and
+        frame clip, and return them to the caller.
+
+        (WebCore::DocumentMarkerController::addMarker):
+        (WebCore::DocumentMarkerController::markerContainingPoint):
+        (WebCore::DocumentMarkerController::markersFor):
+        (WebCore::DocumentMarkerController::repaintMarkers):
+        (WebCore::DocumentMarkerController::shiftMarkers):
+        (DocumentMarkerController::setMarkersActive):
+        (DocumentMarkerController::hasMarkers):
+        Modern iteration.
+        
+        (WebCore::DocumentMarkerController::invalidateRenderedRectsForMarkersInRect): Deleted.
+        * dom/DocumentMarkerController.h:
+
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+        Pass the Document to the DocumentMarkerController.
+
+        * dom/RenderedDocumentMarker.h:
+        (WebCore::RenderedDocumentMarker::contains):
+        (WebCore::RenderedDocumentMarker::setUnclippedAbsoluteRects):
+        (WebCore::RenderedDocumentMarker::unclippedAbsoluteRects):
+        (WebCore::RenderedDocumentMarker::invalidate):
+        (WebCore::RenderedDocumentMarker::isValid):
+        (WebCore::RenderedDocumentMarker::addRenderedRect): Deleted.
+        (WebCore::RenderedDocumentMarker::renderedRects): Deleted.
+        Instead of keeping &quot;rendered&quot; rects, keep unclipped rects in absolute
+        document coordinates. Invalidation will happen wholesale instead of
+        based on dirty rects, because computation no longer happens at paint
+        time, so it's safe to throw all of the rects away.
+        Keep track of whether we have valid rects or not.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::countMatchesForText):
+        We don't need to do a fake whole-document paint just to compute the
+        document marker rects. They are computed on demand, using layout information
+        instead of paint-time information.
+
+        * page/ChromeClient.h:
+        Remove an unnecessary semicolon.
+        Add didInvalidateDocumentMarkerRects, which DocumentMarkerController
+        will call whenever document marker rects are invalidated (and when e.g.
+        the find holes PageOverlay should repaint itself).
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::layout):
+        Invalidate document marker's layout-computed rects after layout is complete.
+        They'll be lazily recomputed when next requested.
+
+        (WebCore::FrameView::willPaintContents):
+        Remove the pre-painting invalidation of document marker rects.
+
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::paintTextMatchMarker):
+        (WebCore::InlineTextBox::paintDocumentMarker): Deleted.
+        (WebCore::InlineTextBox::computeRectForReplacementMarker): Deleted.
+        (WebCore::InlineTextBox::paintDocumentMarkers): Deleted.
+        Don't bother computing rendered rects for document markers at paint time.
+        Just do the actual painting work (which, for replacement markers, is
+        nothing at all).
+
+        * rendering/InlineTextBox.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::updateLayerPositions):
+        (WebCore::RenderLayer::updateLayerPositionsAfterScroll):
+        When RenderLayers move, invalidate document marker rects.
+
+        * rendering/svg/SVGInlineFlowBox.cpp:
+        (WebCore::SVGInlineFlowBox::paint):
+        (WebCore::SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer): Deleted.
+        * rendering/svg/SVGInlineFlowBox.h:
+        * rendering/svg/SVGRootInlineBox.cpp:
+        (WebCore::SVGRootInlineBox::paint):
+        Don't bother computing rendered rects for document markers at paint time.
+
+        * testing/Internals.cpp:
+        (WebCore::markerTypeFrom):
+        (WebCore::markerTypesFrom):
+        Add markerTypeFrom, which returns MarkerType enum values for the input string
+        instead of a MarkerTypes class.
+
+        (WebCore::Internals::dumpMarkerRects):
+        Dump all markers for the given type, and request them from DocumentMarkerController
+        instead of from the RenderedDocumentMarker, because we want fully clipped
+        rects, which can only be obtained from DocumentMarkerController.
+
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::getTextRectangles):
+        Avoid enclosing unnecessarily, to avoid inflating zero-width text rects
+        to have a non-zero width. Callers appear to be OK with non-integral positions.
+
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
</ins><span class="cx"> 2015-09-30  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r190262): User media unit test failures after r190262
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/dom/Document.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -457,7 +457,7 @@
</span><span class="cx">     , m_frameElementsShouldIgnoreScrolling(false)
</span><span class="cx">     , m_updateFocusAppearanceRestoresSelection(false)
</span><span class="cx">     , m_ignoreDestructiveWriteCount(0)
</span><del>-    , m_markers(std::make_unique&lt;DocumentMarkerController&gt;())
</del><ins>+    , m_markers(std::make_unique&lt;DocumentMarkerController&gt;(*this))
</ins><span class="cx">     , m_updateFocusAppearanceTimer(*this, &amp;Document::updateFocusAppearanceTimerFired)
</span><span class="cx">     , m_cssTarget(nullptr)
</span><span class="cx">     , m_processingLoadEvent(false)
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentMarkerControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/DocumentMarkerController.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/DocumentMarkerController.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/dom/DocumentMarkerController.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -27,9 +27,13 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;DocumentMarkerController.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;Chrome.h&quot;
+#include &quot;ChromeClient.h&quot;
+#include &quot;MainFrame.h&quot;
</ins><span class="cx"> #include &quot;NodeTraversal.h&quot;
</span><span class="cx"> #include &quot;Range.h&quot;
</span><span class="cx"> #include &quot;RenderBlockFlow.h&quot;
</span><ins>+#include &quot;RenderLayer.h&quot;
</ins><span class="cx"> #include &quot;RenderText.h&quot;
</span><span class="cx"> #include &quot;RenderedDocumentMarker.h&quot;
</span><span class="cx"> #include &quot;TextIterator.h&quot;
</span><span class="lines">@@ -42,8 +46,8 @@
</span><span class="cx">     return m_possiblyExistingMarkerTypes.intersects(types);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-DocumentMarkerController::DocumentMarkerController()
-    : m_possiblyExistingMarkerTypes(0)
</del><ins>+DocumentMarkerController::DocumentMarkerController(Document&amp; document)
+    : m_document(document)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -59,7 +63,6 @@
</span><span class="cx"> 
</span><span class="cx"> void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String&amp; description)
</span><span class="cx"> {
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         addMarker(&amp;textPiece-&gt;startContainer(), DocumentMarker(type, textPiece-&gt;startOffset(), textPiece-&gt;endOffset(), description));
</span><span class="lines">@@ -68,7 +71,6 @@
</span><span class="cx"> 
</span><span class="cx"> void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type)
</span><span class="cx"> {
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         addMarker(&amp;textPiece-&gt;startContainer(), DocumentMarker(type, textPiece-&gt;startOffset(), textPiece-&gt;endOffset()));
</span><span class="lines">@@ -89,27 +91,17 @@
</span><span class="cx"> 
</span><span class="cx"> void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch)
</span><span class="cx"> {
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         unsigned startOffset = textPiece-&gt;startOffset();
</span><span class="cx">         unsigned endOffset = textPiece-&gt;endOffset();
</span><span class="cx">         addMarker(&amp;textPiece-&gt;startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
</span><del>-        if (endOffset &gt; startOffset) {
-            // Rendered rects for markers in WebKit are not populated until each time
-            // the markers are painted. However, we need it to happen sooner, because
-            // the whole purpose of tickmarks on the scrollbar is to show where
-            // matches off-screen are (that haven't been painted yet).
-            Vector&lt;RenderedDocumentMarker*&gt; markers = markersFor(&amp;textPiece-&gt;startContainer());
-            markers[markers.size() - 1]-&gt;addRenderedRect(range-&gt;absoluteBoundingBox());
-        }
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String&amp; description, const Vector&lt;String&gt;&amp; interpretations, const RetainPtr&lt;id&gt;&amp; metadata)
</span><span class="cx"> {
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         addMarker(&amp;textPiece-&gt;startContainer(), DocumentMarker(type, textPiece-&gt;startOffset(), textPiece-&gt;endOffset(), description, interpretations, metadata));
</span><span class="lines">@@ -123,7 +115,6 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     size_t numberOfAlternatives = interpretations.size() - 1;
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         DocumentMarker marker(DocumentMarker::DictationPhraseWithAlternatives, textPiece-&gt;startOffset(), textPiece-&gt;endOffset(), &quot;&quot;, Vector&lt;String&gt;(numberOfAlternatives), RetainPtr&lt;id&gt;());
</span><span class="lines">@@ -135,7 +126,6 @@
</span><span class="cx"> 
</span><span class="cx"> void DocumentMarkerController::addDictationResultMarker(Range* range, const RetainPtr&lt;id&gt;&amp; metadata)
</span><span class="cx"> {
</span><del>-    // Use a TextIterator to visit the potentially multiple nodes the range covers.
</del><span class="cx">     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
</span><span class="cx">         RefPtr&lt;Range&gt; textPiece = markedText.range();
</span><span class="cx">         addMarker(&amp;textPiece-&gt;startContainer(), DocumentMarker(DocumentMarker::DictationResult, textPiece-&gt;startOffset(), textPiece-&gt;endOffset(), String(), Vector&lt;String&gt;(), metadata));
</span><span class="lines">@@ -157,6 +147,150 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void updateRenderedRectsForMarker(RenderedDocumentMarker&amp; marker, Node&amp; node)
+{
+    ASSERT(!node.document().view() || !node.document().view()-&gt;needsLayout());
+
+    // FIXME: We should refactor this so that we don't use Range (because we only have one Node), but still share code with absoluteTextQuads().
+    RefPtr&lt;Range&gt; markerRange = Range::create(node.document(), &amp;node, marker.startOffset(), &amp;node, marker.endOffset());
+    if (!markerRange)
+        return;
+    Vector&lt;FloatQuad&gt; absoluteMarkerQuads;
+    markerRange-&gt;absoluteTextQuads(absoluteMarkerQuads, true);
+
+    Vector&lt;FloatRect&gt; absoluteMarkerRects;
+    absoluteMarkerRects.reserveInitialCapacity(absoluteMarkerQuads.size());
+    for (const auto&amp; quad : absoluteMarkerQuads)
+        absoluteMarkerRects.append(quad.boundingBox());
+
+    marker.setUnclippedAbsoluteRects(absoluteMarkerRects);
+}
+
+void DocumentMarkerController::invalidateRectsForAllMarkers()
+{
+    if (!hasMarkers())
+        return;
+
+    for (auto&amp; markers : m_markers.values()) {
+        for (auto&amp; marker : *markers)
+            marker.invalidate();
+    }
+
+    if (Page* page = m_document.page())
+        page-&gt;chrome().client().didInvalidateDocumentMarkerRects();
+}
+
+void DocumentMarkerController::invalidateRectsForMarkersInNode(Node&amp; node)
+{
+    if (!hasMarkers())
+        return;
+
+    MarkerList* markers = m_markers.get(&amp;node);
+    ASSERT(markers);
+
+    for (auto&amp; marker : *markers)
+        marker.invalidate();
+
+    if (Page* page = m_document.page())
+        page-&gt;chrome().client().didInvalidateDocumentMarkerRects();
+}
+
+static void updateMainFrameLayoutIfNeeded(Document&amp; document)
+{
+    Frame* frame = document.frame();
+    if (!frame)
+        return;
+
+    FrameView* mainFrameView = frame-&gt;mainFrame().view();
+    if (!mainFrameView)
+        return;
+
+    mainFrameView-&gt;updateLayoutAndStyleIfNeededRecursive();
+}
+
+void DocumentMarkerController::updateRectsForInvalidatedMarkersOfType(DocumentMarker::MarkerType markerType)
+{
+    if (!possiblyHasMarkers(markerType))
+        return;
+    ASSERT(!(m_markers.isEmpty()));
+
+    bool needsLayoutIfAnyRectsAreDirty = true;
+
+    for (auto&amp; nodeAndMarkers : m_markers) {
+        Node&amp; node = *nodeAndMarkers.key;
+        for (auto&amp; marker : *nodeAndMarkers.value) {
+            if (marker.type() != markerType)
+                continue;
+
+            if (marker.isValid())
+                continue;
+
+            // We'll do up to one layout per call if we have any dirty markers.
+            if (needsLayoutIfAnyRectsAreDirty) {
+                updateMainFrameLayoutIfNeeded(m_document);
+                needsLayoutIfAnyRectsAreDirty = false;
+            }
+
+            updateRenderedRectsForMarker(marker, node);
+        }
+    }
+}
+
+Vector&lt;FloatRect&gt; DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
+{
+    Vector&lt;FloatRect&gt; result;
+
+    if (!possiblyHasMarkers(markerType))
+        return result;
+    ASSERT(!(m_markers.isEmpty()));
+
+    Frame* frame = m_document.frame();
+    if (!frame)
+        return result;
+    FrameView* frameView = frame-&gt;view();
+    if (!frameView)
+        return result;
+
+    updateRectsForInvalidatedMarkersOfType(markerType);
+
+    bool isSubframe = !frame-&gt;isMainFrame();
+    IntRect subframeClipRect;
+    if (isSubframe)
+        subframeClipRect = frameView-&gt;windowToContents(frameView-&gt;windowClipRect());
+
+    for (auto&amp; nodeAndMarkers : m_markers) {
+        Node&amp; node = *nodeAndMarkers.key;
+        FloatRect overflowClipRect;
+        if (RenderObject* renderer = node.renderer())
+            overflowClipRect = renderer-&gt;absoluteClippedOverflowRect();
+        for (auto&amp; marker : *nodeAndMarkers.value) {
+            if (marker.type() != markerType)
+                continue;
+
+            auto renderedRects = marker.unclippedAbsoluteRects();
+
+            // Clip document markers by their overflow clip.
+            if (node.renderer()) {
+                for (auto&amp; rect : renderedRects)
+                    rect.intersect(overflowClipRect);
+            }
+
+            // Clip subframe document markers by their frame.
+            if (isSubframe) {
+                for (auto&amp; rect : renderedRects)
+                    rect.intersect(subframeClipRect);
+            }
+
+            for (const auto&amp; rect : renderedRects) {
+                if (!rect.isEmpty())
+                    result.append(rect);
+            }
+        }
+    }
+    
+    return result;
+}
+
</ins><span class="cx"> // Markers are stored in order sorted by their start offset.
</span><span class="cx"> // Markers of the same type do not overlap each other.
</span><span class="cx"> 
</span><span class="lines">@@ -233,9 +367,10 @@
</span><span class="cx">         list-&gt;insert(i, RenderedDocumentMarker(toInsert));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // repaint the affected node
</del><span class="cx">     if (node-&gt;renderer())
</span><span class="cx">         node-&gt;renderer()-&gt;repaint();
</span><ins>+
+    invalidateRectsForMarkersInNode(*node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // copies markers from srcNode to dstNode, applying the specified shift delta to the copies.  The shift is
</span><span class="lines">@@ -277,7 +412,6 @@
</span><span class="cx">         addMarker(dstNode, marker);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // repaint the affected node
</del><span class="cx">     if (docDirty &amp;&amp; dstNode-&gt;renderer())
</span><span class="cx">         dstNode-&gt;renderer()-&gt;repaint();
</span><span class="cx"> }
</span><span class="lines">@@ -343,7 +477,6 @@
</span><span class="cx">             m_possiblyExistingMarkerTypes = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // repaint the affected node
</del><span class="cx">     if (docDirty &amp;&amp; node-&gt;renderer())
</span><span class="cx">         node-&gt;renderer()-&gt;repaint();
</span><span class="cx"> }
</span><span class="lines">@@ -351,19 +484,13 @@
</span><span class="cx"> DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint&amp; point, DocumentMarker::MarkerType markerType)
</span><span class="cx"> {
</span><span class="cx">     if (!possiblyHasMarkers(markerType))
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx">     ASSERT(!(m_markers.isEmpty()));
</span><span class="cx"> 
</span><del>-    // outer loop: process each node that contains any markers
-    MarkerMap::iterator end = m_markers.end();
-    for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
-        // inner loop; process each marker in this node
-        MarkerList* list = nodeIterator-&gt;value.get();
-        unsigned markerCount = list-&gt;size();
-        for (unsigned markerIndex = 0; markerIndex &lt; markerCount; ++markerIndex) {
-            RenderedDocumentMarker&amp; marker = list-&gt;at(markerIndex);
</del><ins>+    updateRectsForInvalidatedMarkersOfType(markerType);
</ins><span class="cx"> 
</span><del>-            // skip marker that is wrong type
</del><ins>+    for (auto&amp; nodeAndMarkers : m_markers) {
+        for (auto&amp; marker : *nodeAndMarkers.value) {
</ins><span class="cx">             if (marker.type() != markerType)
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="lines">@@ -372,7 +499,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return 0;
</del><ins>+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Vector&lt;RenderedDocumentMarker*&gt; DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes)
</span><span class="lines">@@ -382,9 +509,9 @@
</span><span class="cx">     if (!list)
</span><span class="cx">         return result;
</span><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt; list-&gt;size(); ++i) {
-        if (markerTypes.contains(list-&gt;at(i).type()))
-            result.append(&amp;(list-&gt;at(i)));
</del><ins>+    for (auto&amp; marker : *list) {
+        if (markerTypes.contains(marker.type()))
+            result.append(&amp;marker);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return result;
</span><span class="lines">@@ -415,34 +542,6 @@
</span><span class="cx">     return foundMarkers;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;IntRect&gt; DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
-{
-    Vector&lt;IntRect&gt; result;
-
-    if (!possiblyHasMarkers(markerType))
-        return result;
-    ASSERT(!(m_markers.isEmpty()));
-
-    // outer loop: process each node
-    MarkerMap::iterator end = m_markers.end();
-    for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
-        // inner loop; process each marker in this node
-        MarkerList* list = nodeIterator-&gt;value.get();
-        unsigned markerCount = list-&gt;size();
-        for (unsigned markerIndex = 0; markerIndex &lt; markerCount; ++markerIndex) {
-            const RenderedDocumentMarker&amp; marker = list-&gt;at(markerIndex);
-
-            // skip marker that is wrong type
-            if (marker.type() != markerType)
-                continue;
-
-            result.appendVector(marker.renderedRects());
-        }
-    }
-
-    return result;
-}
-
</del><span class="cx"> void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
</span><span class="cx"> {
</span><span class="cx">     if (!possiblyHasMarkers(markerTypes))
</span><span class="lines">@@ -527,10 +626,7 @@
</span><span class="cx">         // inner loop: process each marker in the current node
</span><span class="cx">         MarkerList* list = i-&gt;value.get();
</span><span class="cx">         bool nodeNeedsRepaint = false;
</span><del>-        for (size_t i = 0; i != list-&gt;size(); ++i) {
-            DocumentMarker marker = list-&gt;at(i);
-
-            // skip nodes that are not of the specified type
</del><ins>+        for (auto&amp; marker : *list) {
</ins><span class="cx">             if (markerTypes.contains(marker.type())) {
</span><span class="cx">                 nodeNeedsRepaint = true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -546,19 +642,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect&amp; r)
-{
-    // outer loop: process each markered node in the document
-    MarkerMap::iterator end = m_markers.end();
-    for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
-
-        // inner loop: process each rect in the current node
-        MarkerList* list = i-&gt;value.get();
-        for (size_t listIndex = 0; listIndex &lt; list-&gt;size(); ++listIndex)
-            list-&gt;at(listIndex).invalidate(r);
-    }
-}
-
</del><span class="cx"> void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
</span><span class="cx"> {
</span><span class="cx">     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
</span><span class="lines">@@ -569,9 +652,10 @@
</span><span class="cx">     if (!list)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    bool docDirty = false;
</del><ins>+    bool didShiftMarker = false;
</ins><span class="cx">     for (size_t i = 0; i != list-&gt;size(); ) {
</span><span class="cx">         RenderedDocumentMarker&amp; marker = list-&gt;at(i);
</span><ins>+        // FIXME: How can this possibly be iOS-specific code?
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         int targetStartOffset = marker.startOffset() + delta;
</span><span class="cx">         int targetEndOffset = marker.endOffset() + delta;
</span><span class="lines">@@ -583,10 +667,7 @@
</span><span class="cx">         if (marker.startOffset() &gt;= startOffset) {
</span><span class="cx">             ASSERT((int)marker.startOffset() + delta &gt;= 0);
</span><span class="cx">             marker.shiftOffsets(delta);
</span><del>-            docDirty = true;
-
-            // Marker moved, so previously-computed rendered rectangle is now invalid
-            marker.invalidate();
</del><ins>+            didShiftMarker = true;
</ins><span class="cx"> #if !PLATFORM(IOS)
</span><span class="cx">         }
</span><span class="cx"> #else
</span><span class="lines">@@ -598,18 +679,18 @@
</span><span class="cx">                 continue;
</span><span class="cx">             }
</span><span class="cx">             marker.setEndOffset(targetEndOffset &lt; node-&gt;maxCharacterOffset() ? targetEndOffset : node-&gt;maxCharacterOffset());
</span><del>-            docDirty = true;
-
-            // Marker moved, so previously-computed rendered rectangle is now invalid
-            marker.invalidate();
</del><ins>+            didShiftMarker = true;
</ins><span class="cx">         }
</span><span class="cx"> #endif
</span><span class="cx">         ++i;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // repaint the affected node
-    if (docDirty &amp;&amp; node-&gt;renderer())
-        node-&gt;renderer()-&gt;repaint();
</del><ins>+    if (didShiftMarker) {
+        invalidateRectsForMarkersInNode(*node);
+
+        if (node-&gt;renderer())
+            node-&gt;renderer()-&gt;repaint();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DocumentMarkerController::setMarkersActive(Range* range, bool active)
</span><span class="lines">@@ -636,10 +717,8 @@
</span><span class="cx">     if (!list)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    bool docDirty = false;
-    for (size_t i = 0; i != list-&gt;size(); ++i) {
-        DocumentMarker&amp; marker = list-&gt;at(i);
-
</del><ins>+    bool didActivateMarker = false;
+    for (auto&amp; marker : *list) {
</ins><span class="cx">         // Markers are returned in order, so stop if we are now past the specified range.
</span><span class="cx">         if (marker.startOffset() &gt;= endOffset)
</span><span class="cx">             break;
</span><span class="lines">@@ -649,11 +728,10 @@
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         marker.setActiveMatch(active);
</span><del>-        docDirty = true;
</del><ins>+        didActivateMarker = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // repaint the affected node
-    if (docDirty &amp;&amp; node-&gt;renderer())
</del><ins>+    if (didActivateMarker &amp;&amp; node-&gt;renderer())
</ins><span class="cx">         node-&gt;renderer()-&gt;repaint();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentMarkerControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/DocumentMarkerController.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/DocumentMarkerController.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/dom/DocumentMarkerController.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class Document;
</ins><span class="cx"> class LayoutPoint;
</span><span class="cx"> class LayoutRect;
</span><span class="cx"> class Node;
</span><span class="lines">@@ -45,7 +46,7 @@
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(DocumentMarkerController); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx"> 
</span><del>-    DocumentMarkerController();
</del><ins>+    DocumentMarkerController(Document&amp;);
</ins><span class="cx">     ~DocumentMarkerController();
</span><span class="cx"> 
</span><span class="cx">     void detach();
</span><span class="lines">@@ -78,17 +79,22 @@
</span><span class="cx">     WEBCORE_EXPORT void removeMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
</span><span class="cx">     void removeMarkers(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
</span><span class="cx">     void repaintMarkers(DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
</span><del>-    void invalidateRenderedRectsForMarkersInRect(const LayoutRect&amp;);
</del><span class="cx">     void shiftMarkers(Node*, unsigned startOffset, int delta);
</span><span class="cx">     void setMarkersActive(Range*, bool);
</span><span class="cx">     void setMarkersActive(Node*, unsigned startOffset, unsigned endOffset, bool);
</span><span class="cx"> 
</span><del>-    DocumentMarker* markerContainingPoint(const LayoutPoint&amp;, DocumentMarker::MarkerType);
</del><span class="cx">     WEBCORE_EXPORT Vector&lt;RenderedDocumentMarker*&gt; markersFor(Node*, DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
</span><span class="cx">     WEBCORE_EXPORT Vector&lt;RenderedDocumentMarker*&gt; markersInRange(Range*, DocumentMarker::MarkerTypes);
</span><del>-    WEBCORE_EXPORT Vector&lt;IntRect&gt; renderedRectsForMarkers(DocumentMarker::MarkerType);
</del><span class="cx">     void clearDescriptionOnMarkersIntersectingRange(Range*, DocumentMarker::MarkerTypes);
</span><span class="cx"> 
</span><ins>+    WEBCORE_EXPORT void updateRectsForInvalidatedMarkersOfType(DocumentMarker::MarkerType);
+
+    void invalidateRectsForAllMarkers();
+    void invalidateRectsForMarkersInNode(Node&amp;);
+
+    DocumentMarker* markerContainingPoint(const LayoutPoint&amp;, DocumentMarker::MarkerType);
+    WEBCORE_EXPORT Vector&lt;FloatRect&gt; renderedRectsForMarkers(DocumentMarker::MarkerType);
+
</ins><span class="cx"> #if ENABLE(TREE_DEBUGGING)
</span><span class="cx">     void showMarkers() const;
</span><span class="cx"> #endif
</span><span class="lines">@@ -103,7 +109,8 @@
</span><span class="cx"> 
</span><span class="cx">     MarkerMap m_markers;
</span><span class="cx">     // Provide a quick way to determine whether a particular marker type is absent without going through the map.
</span><del>-    DocumentMarker::MarkerTypes m_possiblyExistingMarkerTypes;
</del><ins>+    DocumentMarker::MarkerTypes m_possiblyExistingMarkerTypes { 0 };
+    Document&amp; m_document;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomRenderedDocumentMarkerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/RenderedDocumentMarker.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/RenderedDocumentMarker.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/dom/RenderedDocumentMarker.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -39,30 +39,39 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool contains(const LayoutPoint&amp; point) const
</del><ins>+    bool contains(const FloatPoint&amp; point) const
</ins><span class="cx">     {
</span><del>-        for (const auto&amp; rect : m_renderedRects) {
</del><ins>+        ASSERT(m_isValid);
+        for (const auto&amp; rect : m_rects) {
</ins><span class="cx">             if (rect.contains(point))
</span><span class="cx">                 return true;
</span><span class="cx">         }
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void addRenderedRect(const LayoutRect&amp; r) { m_renderedRects.append(r); }
-    const Vector&lt;LayoutRect, 1&gt;&amp; renderedRects() const { return m_renderedRects; }
-    void invalidate(const LayoutRect&amp; r)
</del><ins>+    void setUnclippedAbsoluteRects(Vector&lt;FloatRect&gt;&amp; rects)
</ins><span class="cx">     {
</span><del>-        for (const auto&amp; rect : m_renderedRects) {
-            if (rect.intersects(r)) {
-                invalidate();
-                return;
-            }
-        }
</del><ins>+        m_isValid = true;
+        m_rects = rects;
</ins><span class="cx">     }
</span><del>-    void invalidate() { m_renderedRects.clear(); }
</del><span class="cx"> 
</span><ins>+    const Vector&lt;FloatRect, 1&gt;&amp; unclippedAbsoluteRects() const
+    {
+        ASSERT(m_isValid);
+        return m_rects;
+    }
+
+    void invalidate()
+    {
+        m_isValid = false;
+        m_rects.clear();
+    }
+
+    bool isValid() const { return m_isValid; }
+
</ins><span class="cx"> private:
</span><del>-    Vector&lt;LayoutRect, 1&gt; m_renderedRects;
</del><ins>+    Vector&lt;FloatRect, 1&gt; m_rects;
+    bool m_isValid { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/editing/Editor.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -3230,25 +3230,6 @@
</span><span class="cx">             searchRange-&gt;setEnd(shadowTreeRoot, shadowTreeRoot-&gt;countChildNodes(), IGNORE_EXCEPTION);
</span><span class="cx">     } while (true);
</span><span class="cx"> 
</span><del>-    if (markMatches || matches) {
-        // Do a &quot;fake&quot; paint in order to execute the code that computes the rendered rect for each text match.
-        if (m_frame.view() &amp;&amp; m_frame.contentRenderer()) {
-            document().updateLayout(); // Ensure layout is up to date.
-            // FIXME: unclear if we need LegacyIOSDocumentVisibleRect.
-            // FIXME: this should probably look at paintsEntireContents()
-            LayoutRect visibleRect = m_frame.view()-&gt;visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
-            if (!visibleRect.isEmpty()) {
-                GraphicsContext context((PlatformGraphicsContext*)0);
-                context.setPaintingDisabled(true);
-
-                PaintBehavior oldBehavior = m_frame.view()-&gt;paintBehavior();
-                m_frame.view()-&gt;setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
-                m_frame.view()-&gt;paintContents(context, enclosingIntRect(visibleRect));
-                m_frame.view()-&gt;setPaintBehavior(oldBehavior);
-            }
-        }
-    }
-
</del><span class="cx">     return matchCount;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingFrameSelectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/FrameSelection.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -2103,7 +2103,7 @@
</span><span class="cx">     range-&gt;absoluteTextQuads(quads, textRectHeight == TextRectangleHeight::SelectionHeight);
</span><span class="cx"> 
</span><span class="cx">     for (const auto&amp; quad : quads)
</span><del>-        rectangles.append(quad.enclosingBoundingBox());
</del><ins>+        rectangles.append(quad.boundingBox());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Scans logically forward from &quot;start&quot;, including any child frames.
</span></span></pre></div>
<a id="trunkSourceWebCorepageChromeClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/ChromeClient.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/ChromeClient.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/page/ChromeClient.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -458,9 +458,11 @@
</span><span class="cx">     virtual void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&amp;) { }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO) &amp;&amp; USE(GSTREAMER)
</span><del>-    virtual void requestInstallMissingMediaPlugins(const String&amp; /*details*/, const String&amp; /*description*/, MediaPlayerRequestInstallMissingPluginsCallback&amp;) { };
</del><ins>+    virtual void requestInstallMissingMediaPlugins(const String&amp; /*details*/, const String&amp; /*description*/, MediaPlayerRequestInstallMissingPluginsCallback&amp;) { }
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    virtual void didInvalidateDocumentMarkerRects() { }
+
</ins><span class="cx"> protected:
</span><span class="cx">     virtual ~ChromeClient() { }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameView.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameView.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/page/FrameView.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1480,6 +1480,8 @@
</span><span class="cx">     if (document.hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
</span><span class="cx">         updateOverflowStatus(layoutWidth() &lt; contentsWidth(), layoutHeight() &lt; contentsHeight());
</span><span class="cx"> 
</span><ins>+    frame().document()-&gt;markers().invalidateRectsForAllMarkers();
+
</ins><span class="cx">     if (!m_postLayoutTasksTimer.isActive()) {
</span><span class="cx">         if (!m_inSynchronousPostLayout) {
</span><span class="cx">             if (inChildFrameLayoutWithFrameFlattening)
</span><span class="lines">@@ -3925,7 +3927,7 @@
</span><span class="cx">     adjustTiledBackingCoverage();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FrameView::willPaintContents(GraphicsContext&amp; context, const IntRect&amp; dirtyRect, PaintingState&amp; paintingState)
</del><ins>+void FrameView::willPaintContents(GraphicsContext&amp; context, const IntRect&amp;, PaintingState&amp; paintingState)
</ins><span class="cx"> {
</span><span class="cx">     Document* document = frame().document();
</span><span class="cx"> 
</span><span class="lines">@@ -3951,9 +3953,6 @@
</span><span class="cx">         if (parentView-&gt;paintBehavior() &amp; PaintBehaviorFlattenCompositingLayers)
</span><span class="cx">             m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
</span><span class="cx">     }
</span><del>-    
-    if (m_paintBehavior == PaintBehaviorNormal)
-        document-&gt;markers().invalidateRenderedRectsForMarkersInRect(dirtyRect);
</del><span class="cx"> 
</span><span class="cx">     if (document-&gt;printing())
</span><span class="cx">         m_paintBehavior |= PaintBehaviorFlattenCompositingLayers;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingInlineTextBoxcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/InlineTextBox.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1098,14 +1098,6 @@
</span><span class="cx">         IntRect markerRect = enclosingIntRect(selectionRect);
</span><span class="cx">         start = markerRect.x() - startPoint.x();
</span><span class="cx">         width = markerRect.width();
</span><del>-        
-        // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to
-        // display a toolTip. We don't do this for misspelling markers.
-        if (grammar || isDictationMarker) {
-            markerRect.move(-boxOrigin.x(), -boxOrigin.y());
-            markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
-            marker.addRenderedRect(markerRect);
-        }
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
</span><span class="lines">@@ -1130,58 +1122,29 @@
</span><span class="cx"> 
</span><span class="cx"> void InlineTextBox::paintTextMatchMarker(GraphicsContext&amp; context, const FloatPoint&amp; boxOrigin, RenderedDocumentMarker&amp; marker, const RenderStyle&amp; style, const FontCascade&amp; font)
</span><span class="cx"> {
</span><del>-    LayoutUnit selectionHeight = this-&gt;selectionHeight();
</del><ins>+    if (!renderer().frame().editor().markedTextMatchesAreHighlighted())
+        return;
</ins><span class="cx"> 
</span><ins>+    Color color = marker.activeMatch() ? renderer().theme().platformActiveTextSearchHighlightColor() : renderer().theme().platformInactiveTextSearchHighlightColor();
+    GraphicsContextStateSaver stateSaver(context);
+    updateGraphicsContext(context, TextPaintStyle(color, style.colorSpace())); // Don't draw text at all!
+
+    // Use same y positioning and height as for selection, so that when the selection and this highlight are on
+    // the same word there are no pieces sticking out.
+    LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+    LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, 0, this-&gt;selectionHeight());
+
</ins><span class="cx">     int sPos = std::max&lt;int&gt;(marker.startOffset() - m_start, 0);
</span><span class="cx">     int ePos = std::min&lt;int&gt;(marker.endOffset() - m_start, m_len);
</span><span class="cx">     TextRun run = constructTextRun(style, font);
</span><ins>+    font.adjustSelectionRectForText(run, selectionRect, sPos, ePos);
</ins><span class="cx"> 
</span><del>-    // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates.
-    // FIXME: figure out how renderedRect and selectionRect are different.
-    LayoutRect renderedRect = LayoutRect(LayoutPoint(x(), selectionTop()), FloatSize(0, selectionHeight));
-    font.adjustSelectionRectForText(run, renderedRect, sPos, ePos);
-    IntRect markerRect = enclosingIntRect(renderedRect);
-    markerRect = renderer().localToAbsoluteQuad(FloatQuad(markerRect)).enclosingBoundingBox();
-    markerRect.intersect(enclosingIntRect(renderer().absoluteClippedOverflowRect()));
-
-    if (markerRect.isEmpty())
</del><ins>+    if (selectionRect.isEmpty())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    marker.addRenderedRect(markerRect);
-
-    // Optionally highlight the text
-    if (renderer().frame().editor().markedTextMatchesAreHighlighted()) {
-        Color color = marker.activeMatch() ? renderer().theme().platformActiveTextSearchHighlightColor() : renderer().theme().platformInactiveTextSearchHighlightColor();
-        GraphicsContextStateSaver stateSaver(context);
-        updateGraphicsContext(context, TextPaintStyle(color, style.colorSpace())); // Don't draw text at all!
-
-        // Use same y positioning and height as for selection, so that when the selection and this highlight are on
-        // the same word there are no pieces sticking out.
-        LayoutUnit deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
-        LayoutRect selectionRect = LayoutRect(boxOrigin.x(), boxOrigin.y() - deltaY, 0, selectionHeight);
-        font.adjustSelectionRectForText(run, selectionRect, sPos, ePos);
-        context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), run.ltr()), color, style.colorSpace());
-    }
</del><ins>+    context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), run.ltr()), color, style.colorSpace());
</ins><span class="cx"> }
</span><del>-
-void InlineTextBox::computeRectForReplacementMarker(RenderedDocumentMarker&amp; marker, const RenderStyle&amp; style, const FontCascade&amp; font)
-{
-    // Replacement markers are not actually drawn, but their rects need to be computed for hit testing.
-    LayoutUnit top = selectionTop();
-    LayoutUnit h = selectionHeight();
</del><span class="cx">     
</span><del>-    int sPos = std::max(marker.startOffset() - m_start, (unsigned)0);
-    int ePos = std::min(marker.endOffset() - m_start, (unsigned)m_len);
-    TextRun run = constructTextRun(style, font);
-
-    // Compute and store the rect associated with this marker.
-    LayoutRect selectionRect = LayoutRect(LayoutPoint(x(), top), LayoutSize(0, h));
-    font.adjustSelectionRectForText(run, selectionRect, sPos, ePos);
-    IntRect markerRect = enclosingIntRect(selectionRect);
-    markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
-    marker.addRenderedRect(markerRect);
-}
-    
</del><span class="cx"> void InlineTextBox::paintDocumentMarkers(GraphicsContext&amp; context, const FloatPoint&amp; boxOrigin, const RenderStyle&amp; style, const FontCascade&amp; font, bool background)
</span><span class="cx"> {
</span><span class="cx">     if (!renderer().textNode())
</span><span class="lines">@@ -1246,7 +1209,6 @@
</span><span class="cx">                 paintTextMatchMarker(context, boxOrigin, *marker, style, font);
</span><span class="cx">                 break;
</span><span class="cx">             case DocumentMarker::Replacement:
</span><del>-                computeRectForReplacementMarker(*marker, style, font);
</del><span class="cx">                 break;
</span><span class="cx"> #if ENABLE(TELEPHONE_NUMBER_DETECTION)
</span><span class="cx">             case DocumentMarker::TelephoneNumber:
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingInlineTextBoxh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/InlineTextBox.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -164,8 +164,6 @@
</span><span class="cx">     void paintDocumentMarker(GraphicsContext&amp;, const FloatPoint&amp; boxOrigin, RenderedDocumentMarker&amp;, const RenderStyle&amp;, const FontCascade&amp;, bool grammar);
</span><span class="cx">     void paintTextMatchMarker(GraphicsContext&amp;, const FloatPoint&amp; boxOrigin, RenderedDocumentMarker&amp;, const RenderStyle&amp;, const FontCascade&amp;);
</span><span class="cx"> 
</span><del>-    void computeRectForReplacementMarker(RenderedDocumentMarker&amp;, const RenderStyle&amp;, const FontCascade&amp;);
-
</del><span class="cx">     ExpansionBehavior expansionBehavior() const;
</span><span class="cx"> 
</span><span class="cx">     void behavesLikeText() const = delete;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayer.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> #include &quot;DebugPageOverlays.h&quot;
</span><span class="cx"> #include &quot;Document.h&quot;
</span><span class="cx"> #include &quot;DocumentEventQueue.h&quot;
</span><ins>+#include &quot;DocumentMarkerController.h&quot;
</ins><span class="cx"> #include &quot;Element.h&quot;
</span><span class="cx"> #include &quot;EventHandler.h&quot;
</span><span class="cx"> #include &quot;FEColorMatrix.h&quot;
</span><span class="lines">@@ -576,6 +577,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (geometryMap)
</span><span class="cx">         geometryMap-&gt;popMappingsToAncestor(parent());
</span><ins>+
+    renderer().document().markers().invalidateRectsForAllMarkers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
</span><span class="lines">@@ -875,6 +878,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (geometryMap)
</span><span class="cx">         geometryMap-&gt;popMappingsToAncestor(parent());
</span><ins>+
+    renderer().document().markers().invalidateRectsForAllMarkers();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderLayer::positionNewlyCreatedOverflowControls()
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGInlineFlowBoxcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -23,9 +23,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;SVGInlineFlowBox.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;DocumentMarkerController.h&quot;
</del><span class="cx"> #include &quot;GraphicsContext.h&quot;
</span><del>-#include &quot;RenderedDocumentMarker.h&quot;
</del><span class="cx"> #include &quot;SVGInlineTextBox.h&quot;
</span><span class="cx"> #include &quot;SVGRenderingContext.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -52,12 +50,8 @@
</span><span class="cx"> 
</span><span class="cx">     SVGRenderingContext renderingContext(renderer(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
</span><span class="cx">     if (renderingContext.isRenderingPrepared()) {
</span><del>-        for (InlineBox* child = firstChild(); child; child = child-&gt;nextOnLine()) {
-            if (is&lt;SVGInlineTextBox&gt;(*child))
-                computeTextMatchMarkerRectForRenderer(&amp;downcast&lt;SVGInlineTextBox&gt;(*child).renderer());
-
</del><ins>+        for (InlineBox* child = firstChild(); child; child = child-&gt;nextOnLine())
</ins><span class="cx">             child-&gt;paint(paintInfo, paintOffset, 0, 0);
</span><del>-        }
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -72,60 +66,4 @@
</span><span class="cx">     return childRect;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer)
-{
-    ASSERT(textRenderer);
-
-    Text&amp; textNode = textRenderer-&gt;textNode();
-    if (!textNode.inDocument())
-        return;
-
-    RenderStyle&amp; style = textRenderer-&gt;style();
-
-    AffineTransform fragmentTransform;
-    Vector&lt;RenderedDocumentMarker*&gt; markers = textRenderer-&gt;document().markers().markersFor(&amp;textNode);
-    for (auto* marker : markers) {
-        // SVG is only interessted in the TextMatch marker, for now.
-        if (marker-&gt;type() != DocumentMarker::TextMatch)
-            continue;
-
-        FloatRect markerRect;
-        for (InlineTextBox* box = textRenderer-&gt;firstTextBox(); box; box = box-&gt;nextTextBox()) {
-            if (!is&lt;SVGInlineTextBox&gt;(*box))
-                continue;
-
-            auto&amp; textBox = downcast&lt;SVGInlineTextBox&gt;(*box);
-
-            int markerStartPosition = std::max&lt;int&gt;(marker-&gt;startOffset() - textBox.start(), 0);
-            int markerEndPosition = std::min&lt;int&gt;(marker-&gt;endOffset() - textBox.start(), textBox.len());
-
-            if (markerStartPosition &gt;= markerEndPosition)
-                continue;
-
-            int fragmentStartPosition = 0;
-            int fragmentEndPosition = 0;
-
-            const Vector&lt;SVGTextFragment&gt;&amp; fragments = textBox.textFragments();
-            unsigned textFragmentsSize = fragments.size();
-            for (unsigned i = 0; i &lt; textFragmentsSize; ++i) {
-                const SVGTextFragment&amp; fragment = fragments.at(i);
-
-                fragmentStartPosition = markerStartPosition;
-                fragmentEndPosition = markerEndPosition;
-                if (!textBox.mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
-                    continue;
-
-                FloatRect fragmentRect = textBox.selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, &amp;style);
-                fragment.buildFragmentTransform(fragmentTransform);
-                if (!fragmentTransform.isIdentity())
-                    fragmentRect = fragmentTransform.mapRect(fragmentRect);
-
-                markerRect.unite(fragmentRect);
-            }
-        }
-
-        marker-&gt;addRenderedRect(textRenderer-&gt;localToAbsoluteQuad(markerRect).enclosingBoundingBox());
-    }
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGInlineFlowBoxh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineFlowBox.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -42,7 +42,6 @@
</span><span class="cx"> 
</span><span class="cx">     void setLogicalHeight(float h) { m_logicalHeight = h; }
</span><span class="cx">     void paintSelectionBackground(PaintInfo&amp;);
</span><del>-    static void computeTextMatchMarkerRectForRenderer(RenderSVGInlineText*);
</del><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     virtual bool isSVGInlineFlowBox() const override { return true; }
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingsvgSVGRootInlineBoxcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -66,12 +66,8 @@
</span><span class="cx"> 
</span><span class="cx">     SVGRenderingContext renderingContext(renderSVGText(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
</span><span class="cx">     if (renderingContext.isRenderingPrepared()) {
</span><del>-        for (InlineBox* child = firstChild(); child; child = child-&gt;nextOnLine()) {
-            if (is&lt;SVGInlineTextBox&gt;(*child))
-                SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(&amp;downcast&lt;SVGInlineTextBox&gt;(*child).renderer());
-
</del><ins>+        for (InlineBox* child = firstChild(); child; child = child-&gt;nextOnLine())
</ins><span class="cx">             child-&gt;paint(paintInfo, paintOffset, 0, 0);
</span><del>-        }
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/testing/Internals.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -281,37 +281,49 @@
</span><span class="cx">     return InspectorClient::doDispatchMessageOnFrontendPage(frontendPage(), message);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool markerTypesFrom(const String&amp; markerType, DocumentMarker::MarkerTypes&amp; result)
</del><ins>+static bool markerTypeFrom(const String&amp; markerType, DocumentMarker::MarkerType&amp; result)
</ins><span class="cx"> {
</span><del>-    if (markerType.isEmpty() || equalIgnoringCase(markerType, &quot;all&quot;))
-        result = DocumentMarker::AllMarkers();
-    else if (equalIgnoringCase(markerType, &quot;Spelling&quot;))
-        result =  DocumentMarker::Spelling;
</del><ins>+    if (equalIgnoringCase(markerType, &quot;Spelling&quot;))
+        result = DocumentMarker::Spelling;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;Grammar&quot;))
</span><del>-        result =  DocumentMarker::Grammar;
</del><ins>+        result = DocumentMarker::Grammar;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;TextMatch&quot;))
</span><del>-        result =  DocumentMarker::TextMatch;
</del><ins>+        result = DocumentMarker::TextMatch;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;Replacement&quot;))
</span><del>-        result =  DocumentMarker::Replacement;
</del><ins>+        result = DocumentMarker::Replacement;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;CorrectionIndicator&quot;))
</span><del>-        result =  DocumentMarker::CorrectionIndicator;
</del><ins>+        result = DocumentMarker::CorrectionIndicator;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;RejectedCorrection&quot;))
</span><del>-        result =  DocumentMarker::RejectedCorrection;
</del><ins>+        result = DocumentMarker::RejectedCorrection;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;Autocorrected&quot;))
</span><del>-        result =  DocumentMarker::Autocorrected;
</del><ins>+        result = DocumentMarker::Autocorrected;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;SpellCheckingExemption&quot;))
</span><del>-        result =  DocumentMarker::SpellCheckingExemption;
</del><ins>+        result = DocumentMarker::SpellCheckingExemption;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;DeletedAutocorrection&quot;))
</span><del>-        result =  DocumentMarker::DeletedAutocorrection;
</del><ins>+        result = DocumentMarker::DeletedAutocorrection;
</ins><span class="cx">     else if (equalIgnoringCase(markerType, &quot;DictationAlternatives&quot;))
</span><del>-        result =  DocumentMarker::DictationAlternatives;
</del><ins>+        result = DocumentMarker::DictationAlternatives;
</ins><span class="cx"> #if ENABLE(TELEPHONE_NUMBER_DETECTION)
</span><span class="cx">     else if (equalIgnoringCase(markerType, &quot;TelephoneNumber&quot;))
</span><del>-        result =  DocumentMarker::TelephoneNumber;
</del><ins>+        result = DocumentMarker::TelephoneNumber;
</ins><span class="cx"> #endif
</span><span class="cx">     else
</span><span class="cx">         return false;
</span><ins>+    
+    return true;
+}
</ins><span class="cx"> 
</span><ins>+static bool markerTypesFrom(const String&amp; markerType, DocumentMarker::MarkerTypes&amp; result)
+{
+    DocumentMarker::MarkerType singularResult;
+
+    if (markerType.isEmpty() || equalIgnoringCase(markerType, &quot;all&quot;))
+        result = DocumentMarker::AllMarkers();
+    else if (markerTypeFrom(markerType, singularResult))
+        result = singularResult;
+    else
+        return false;
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1043,23 +1055,29 @@
</span><span class="cx">     return marker-&gt;description();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String Internals::dumpMarkerRectsForNode(Node* node, const String&amp; markerType, unsigned index, ExceptionCode&amp; ec)
</del><ins>+String Internals::dumpMarkerRects(const String&amp; markerTypeString, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
-    if (!marker)
</del><ins>+    DocumentMarker::MarkerType markerType;
+    if (!markerTypeFrom(markerTypeString, markerType)) {
+        ec = SYNTAX_ERR;
</ins><span class="cx">         return String();
</span><ins>+    }
+
+    contextDocument()-&gt;markers().updateRectsForInvalidatedMarkersOfType(markerType);
+    auto rects = contextDocument()-&gt;markers().renderedRectsForMarkers(markerType);
+
</ins><span class="cx">     StringBuilder rectString;
</span><del>-    rectString.append(&quot;marker rects: &quot;);
-    for (const auto&amp; rect : marker-&gt;renderedRects()) {
-        rectString.append(&quot;(&quot;);
-        rectString.appendNumber(rect.x().toFloat());
-        rectString.append(&quot;, &quot;);
-        rectString.appendNumber(rect.y().toFloat());
-        rectString.append(&quot;, &quot;);
-        rectString.appendNumber(rect.width().toFloat());
-        rectString.append(&quot;, &quot;);
-        rectString.appendNumber(rect.height().toFloat());
-        rectString.append(&quot;) &quot;);
</del><ins>+    rectString.appendLiteral(&quot;marker rects: &quot;);
+    for (const auto&amp; rect : rects) {
+        rectString.append('(');
+        rectString.appendNumber(rect.x());
+        rectString.appendLiteral(&quot;, &quot;);
+        rectString.appendNumber(rect.y());
+        rectString.appendLiteral(&quot;, &quot;);
+        rectString.appendNumber(rect.width());
+        rectString.appendLiteral(&quot;, &quot;);
+        rectString.appendNumber(rect.height());
+        rectString.appendLiteral(&quot;) &quot;);
</ins><span class="cx">     }
</span><span class="cx">     return rectString.toString();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/testing/Internals.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -158,7 +158,7 @@
</span><span class="cx">     unsigned markerCountForNode(Node*, const String&amp;, ExceptionCode&amp;);
</span><span class="cx">     RefPtr&lt;Range&gt; markerRangeForNode(Node*, const String&amp; markerType, unsigned index, ExceptionCode&amp;);
</span><span class="cx">     String markerDescriptionForNode(Node*, const String&amp; markerType, unsigned index, ExceptionCode&amp;);
</span><del>-    String dumpMarkerRectsForNode(Node*, const String&amp; markerType, unsigned index, ExceptionCode&amp;);
</del><ins>+    String dumpMarkerRects(const String&amp; markerType, ExceptionCode&amp;);
</ins><span class="cx">     void addTextMatchMarker(const Range*, bool isActive);
</span><span class="cx">     void setMarkedTextMatchesAreHighlighted(bool, ExceptionCode&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebCore/testing/Internals.idl        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -131,7 +131,7 @@
</span><span class="cx">     [RaisesException] unsigned long markerCountForNode(Node node, DOMString markerType);
</span><span class="cx">     [RaisesException] Range markerRangeForNode(Node node, DOMString markerType, unsigned long index);
</span><span class="cx">     [RaisesException] DOMString markerDescriptionForNode(Node node, DOMString markerType, unsigned long index);
</span><del>-    [RaisesException] DOMString dumpMarkerRectsForNode(Node node, DOMString markerType, unsigned long index);
</del><ins>+    [RaisesException] DOMString dumpMarkerRects(DOMString markerType);
</ins><span class="cx">     void addTextMatchMarker(Range range, boolean isActive);
</span><span class="cx">     [RaisesException] void setMarkedTextMatchesAreHighlighted(boolean flag);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit/mac/ChangeLog        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-09-30  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
+        Compute document marker rects at use time instead of paint time
+        https://bugs.webkit.org/show_bug.cgi?id=149643
+
+        Reviewed by Darin Adler.
+
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView rectsForTextMatches]):
+
</ins><span class="cx"> 2015-09-16  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         printing does not use minimum page zoom factor
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebHTMLViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebHTMLView.mm (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebHTMLView.mm        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit/mac/WebView/WebHTMLView.mm        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -6862,7 +6862,7 @@
</span><span class="cx">     if (!document)
</span><span class="cx">         return [NSArray array];
</span><span class="cx"> 
</span><del>-    Vector&lt;IntRect&gt; rects = document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
</del><ins>+    Vector&lt;FloatRect&gt; rects = document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
</ins><span class="cx">     unsigned count = rects.size();
</span><span class="cx">     NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
</span><span class="cx">     for (unsigned index = 0; index &lt; count; ++index)
</span></span></pre></div>
<a id="trunkSourceWebKitwinChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/win/ChangeLog (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/win/ChangeLog        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit/win/ChangeLog        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-09-30  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
+        Compute document marker rects at use time instead of paint time
+        https://bugs.webkit.org/show_bug.cgi?id=149643
+
+        Reviewed by Darin Adler.
+
+        * WebView.cpp:
+        (WebView::rectsForTextMatches):
+
</ins><span class="cx"> 2015-09-25  Per Arne Vollan  &lt;peavo@outlook.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WinCairo] Incorrect position for windowless plugins.
</span></span></pre></div>
<a id="trunkSourceWebKitwinWebViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/win/WebView.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/win/WebView.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit/win/WebView.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -3699,15 +3699,15 @@
</span><span class="cx">     do {
</span><span class="cx">         if (Document* document = frame-&gt;document()) {
</span><span class="cx">             IntRect visibleRect = frame-&gt;view()-&gt;visibleContentRect();
</span><del>-            Vector&lt;IntRect&gt; frameRects = document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
</del><ins>+            Vector&lt;FloatRect&gt; frameRects = document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
</ins><span class="cx">             IntPoint frameOffset(-frame-&gt;view()-&gt;scrollOffset().width(), -frame-&gt;view()-&gt;scrollOffset().height());
</span><span class="cx">             frameOffset = frame-&gt;view()-&gt;convertToContainingWindow(frameOffset);
</span><span class="cx"> 
</span><del>-            Vector&lt;IntRect&gt;::iterator end = frameRects.end();
-            for (Vector&lt;IntRect&gt;::iterator it = frameRects.begin(); it &lt; end; it++) {
</del><ins>+            Vector&lt;FloatRect&gt;::iterator end = frameRects.end();
+            for (Vector&lt;FloatRect&gt;::iterator it = frameRects.begin(); it &lt; end; it++) {
</ins><span class="cx">                 it-&gt;intersect(visibleRect);
</span><span class="cx">                 it-&gt;move(frameOffset.x(), frameOffset.y());
</span><del>-                allRects.append(*it);
</del><ins>+                allRects.append(enclosingIntRect(*it));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         frame = incrementFrame(frame, true, false);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit2/ChangeLog        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-09-30  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
+        Compute document marker rects at use time instead of paint time
+        https://bugs.webkit.org/show_bug.cgi?id=149643
+
+        Reviewed by Darin Adler.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::didInvalidateDocumentMarkerRects):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        Plumb the notification about invalidated document marker rects through to FindController.
+
+        * WebProcess/WebPage/FindController.cpp:
+        (WebKit::FindController::updateFindUIAfterPageScroll):
+        Make a document-relative PageOverlay, so that we get fast scrolling.
+
+        (WebKit::FindController::rectsForTextMatchesInRect):
+        Return find hole rects in main-FrameView content coordinates, to 
+        match the document-relative page overlay.
+        We'll only return rects that intersect the passed-in rect, which
+        comes from the dirty rect passed to drawRect.
+
+        (WebKit::FindController::drawRect):
+        Inflate the dirty rect by the border width so that we hit all relevant
+        markers in each tile. Otherwise, we would end up missing the border of a marker
+        that touched the edge of a tile.
+
+        (WebKit::FindController::didInvalidateDocumentMarkerRects):
+        Repaint (for now, the entire overlay) when document marker rects change.
+
+        * WebProcess/WebPage/FindController.h:
+
</ins><span class="cx"> 2015-09-30  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Build error with -DENABLE_SPELLCHECK=OFF
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -1177,4 +1177,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> #endif // ENABLE(VIDEO)
</span><span class="cx"> 
</span><ins>+void WebChromeClient::didInvalidateDocumentMarkerRects()
+{
+    m_page-&gt;findController().didInvalidateDocumentMarkerRects();
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -332,6 +332,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    virtual void didInvalidateDocumentMarkerRects() override;
+
</ins><span class="cx">     String m_cachedToolTip;
</span><span class="cx">     mutable RefPtr&lt;WebFrame&gt; m_cachedFrameSetLargestFrame;
</span><span class="cx">     mutable bool m_cachedMainFrameHasHorizontalScrollbar;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageFindControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -191,7 +191,7 @@
</span><span class="cx">             m_webPage-&gt;mainFrame()-&gt;pageOverlayController().uninstallPageOverlay(m_findPageOverlay, PageOverlay::FadeMode::Fade);
</span><span class="cx">     } else {
</span><span class="cx">         if (!m_findPageOverlay) {
</span><del>-            RefPtr&lt;PageOverlay&gt; findPageOverlay = PageOverlay::create(*this);
</del><ins>+            RefPtr&lt;PageOverlay&gt; findPageOverlay = PageOverlay::create(*this, PageOverlay::OverlayType::Document);
</ins><span class="cx">             m_findPageOverlay = findPageOverlay.get();
</span><span class="cx">             m_webPage-&gt;mainFrame()-&gt;pageOverlayController().installPageOverlay(findPageOverlay.release(), PageOverlay::FadeMode::Fade);
</span><span class="cx">         }
</span><span class="lines">@@ -394,28 +394,26 @@
</span><span class="cx">     updateFindIndicator(*selectedFrame, isShowingOverlay(), false);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Vector&lt;IntRect&gt; FindController::rectsForTextMatches()
</del><ins>+Vector&lt;IntRect&gt; FindController::rectsForTextMatchesInRect(IntRect clipRect)
</ins><span class="cx"> {
</span><span class="cx">     Vector&lt;IntRect&gt; rects;
</span><span class="cx"> 
</span><ins>+    FrameView* mainFrameView = m_webPage-&gt;corePage()-&gt;mainFrame().view();
+
</ins><span class="cx">     for (Frame* frame = &amp;m_webPage-&gt;corePage()-&gt;mainFrame(); frame; frame = frame-&gt;tree().traverseNext()) {
</span><span class="cx">         Document* document = frame-&gt;document();
</span><span class="cx">         if (!document)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        IntRect visibleRect = frame-&gt;view()-&gt;visibleContentRect();
-        Vector&lt;IntRect&gt; frameRects = document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch);
-        IntPoint frameOffset(-frame-&gt;view()-&gt;documentScrollOffsetRelativeToViewOrigin().width(), -frame-&gt;view()-&gt;documentScrollOffsetRelativeToViewOrigin().height());
-        frameOffset = frame-&gt;view()-&gt;convertToContainingWindow(frameOffset);
</del><ins>+        for (FloatRect rect : document-&gt;markers().renderedRectsForMarkers(DocumentMarker::TextMatch)) {
+            if (!frame-&gt;isMainFrame())
+                rect = mainFrameView-&gt;windowToContents(frame-&gt;view()-&gt;contentsToWindow(enclosingIntRect(rect)));
+            rect.intersect(clipRect);
</ins><span class="cx"> 
</span><del>-        for (Vector&lt;IntRect&gt;::iterator it = frameRects.begin(), end = frameRects.end(); it != end; ++it) {
-            it-&gt;intersect(visibleRect);
-
-            if (it-&gt;isEmpty())
</del><ins>+            if (rect.isEmpty())
</ins><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            it-&gt;moveBy(frameOffset);
-            rects.append(*it);
</del><ins>+            rects.append(rect);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -453,9 +451,13 @@
</span><span class="cx"> 
</span><span class="cx"> void FindController::drawRect(PageOverlay&amp;, GraphicsContext&amp; graphicsContext, const IntRect&amp; dirtyRect)
</span><span class="cx"> {
</span><ins>+    const int borderWidth = 1;
+
</ins><span class="cx">     Color overlayBackgroundColor(0.1f, 0.1f, 0.1f, 0.25f);
</span><span class="cx"> 
</span><del>-    Vector&lt;IntRect&gt; rects = rectsForTextMatches();
</del><ins>+    IntRect borderInflatedDirtyRect = dirtyRect;
+    borderInflatedDirtyRect.inflate(borderWidth);
+    Vector&lt;IntRect&gt; rects = rectsForTextMatchesInRect(borderInflatedDirtyRect);
</ins><span class="cx"> 
</span><span class="cx">     // Draw the background.
</span><span class="cx">     graphicsContext.fillRect(dirtyRect, overlayBackgroundColor, ColorSpaceSRGB);
</span><span class="lines">@@ -469,7 +471,7 @@
</span><span class="cx">         // Draw white frames around the holes.
</span><span class="cx">         for (auto&amp; rect : rects) {
</span><span class="cx">             IntRect whiteFrameRect = rect;
</span><del>-            whiteFrameRect.inflate(1);
</del><ins>+            whiteFrameRect.inflate(borderWidth);
</ins><span class="cx">             graphicsContext.fillRect(whiteFrameRect);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -497,4 +499,10 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void FindController::didInvalidateDocumentMarkerRects()
+{
+    if (m_findPageOverlay)
+        m_findPageOverlay-&gt;setNeedsDisplay();
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageFindControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.h (190362 => 190363)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.h        2015-09-30 19:16:51 UTC (rev 190362)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.h        2015-09-30 19:36:37 UTC (rev 190363)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx">     bool isShowingOverlay() const { return m_isShowingFindIndicator &amp;&amp; m_findPageOverlay; }
</span><span class="cx"> 
</span><span class="cx">     void deviceScaleFactorDidChange();
</span><ins>+    void didInvalidateDocumentMarkerRects();
</ins><span class="cx"> 
</span><span class="cx">     void redraw();
</span><span class="cx"> 
</span><span class="lines">@@ -78,7 +79,7 @@
</span><span class="cx">     virtual bool mouseEvent(WebCore::PageOverlay&amp;, const WebCore::PlatformMouseEvent&amp;);
</span><span class="cx">     virtual void drawRect(WebCore::PageOverlay&amp;, WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect);
</span><span class="cx"> 
</span><del>-    Vector&lt;WebCore::IntRect&gt; rectsForTextMatches();
</del><ins>+    Vector&lt;WebCore::IntRect&gt; rectsForTextMatchesInRect(WebCore::IntRect clipRect);
</ins><span class="cx">     bool updateFindIndicator(WebCore::Frame&amp; selectedFrame, bool isShowingOverlay, bool shouldAnimate = true);
</span><span class="cx"> 
</span><span class="cx">     void updateFindUIAfterPageScroll(bool found, const String&amp;, FindOptions, unsigned maxMatchCount);
</span></span></pre>
</div>
</div>

</body>
</html>