<!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>[167714] trunk/Source/WebCore</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/167714">167714</a></dd>
<dt>Author</dt> <dd>hyatt@apple.com</dd>
<dt>Date</dt> <dd>2014-04-23 11:05:33 -0700 (Wed, 23 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[New Multicolumn] Nested columns not working at all.
https://bugs.webkit.org/show_bug.cgi?id=131805

Reviewed by Dean Jackson.

Add support for nested pagination contexts, allowing for an arbitrary level
of nesting of multicolumn layouts. There were a number of things that had to
be patched in order for this to work.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::regionAtBlockOffset):
Make sure RenderMultiColumnFlowThreads just return null for regions at any
block offset. Individual region sets will be created as you cross ancestor
regions eventually, so this is just getting in the way.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::enclosingPaginationLayerInSubtree):
Add a new helper method for obtaining an enclosingPaginationLayer when
constrained by some root. This function ensures you don't accidentally
cross your subtree root when looking for enclosing pagination layers.

(WebCore::RenderLayer::collectFragments):
Patch collectFragments to know how to recur to collect ancestor fragments
in order to apply nested splitting as you cross pagination boundaries.

(WebCore::RenderLayer::updatePaintingInfoForFragments):
(WebCore::RenderLayer::calculateClipRects):
* rendering/RenderLayer.h:
(WebCore::LayerFragment::LayerFragment):
(WebCore::LayerFragment::setRects):
(WebCore::LayerFragment::moveBy):
(WebCore::LayerFragment::intersect):
Improve the LayerFragment so that it caches transformed bounding boxes as
well. This is needed to fix intersectsDamageRect so that it doesn't grab
the wrong bounding box when checking inline layers that are paginated.

* rendering/RenderMultiColumnFlowThread.cpp:
(WebCore::RenderMultiColumnFlowThread::flowThreadDescendantInserted):
Ignore inserted flow threads inside an ancestor flow thread, since we only
care about what the sets do.
        
* rendering/RenderObject.cpp:
(WebCore::RenderObject::insertedIntoTree):
Make sure that nested flow thread layers return themselves when a child
is inserted directly under them.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockcpp">trunk/Source/WebCore/rendering/RenderBlock.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayercpp">trunk/Source/WebCore/rendering/RenderLayer.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayerh">trunk/Source/WebCore/rendering/RenderLayer.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderMultiColumnFlowThreadcpp">trunk/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderObjectcpp">trunk/Source/WebCore/rendering/RenderObject.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/ChangeLog        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2014-04-22  David Hyatt  &lt;hyatt@apple.com&gt;
+
+        [New Multicolumn] Nested columns not working at all.
+        https://bugs.webkit.org/show_bug.cgi?id=131805
+
+        Reviewed by Dean Jackson.
+
+        Add support for nested pagination contexts, allowing for an arbitrary level
+        of nesting of multicolumn layouts. There were a number of things that had to
+        be patched in order for this to work.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::regionAtBlockOffset):
+        Make sure RenderMultiColumnFlowThreads just return null for regions at any
+        block offset. Individual region sets will be created as you cross ancestor
+        regions eventually, so this is just getting in the way.
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::enclosingPaginationLayerInSubtree):
+        Add a new helper method for obtaining an enclosingPaginationLayer when
+        constrained by some root. This function ensures you don't accidentally
+        cross your subtree root when looking for enclosing pagination layers.
+
+        (WebCore::RenderLayer::collectFragments):
+        Patch collectFragments to know how to recur to collect ancestor fragments
+        in order to apply nested splitting as you cross pagination boundaries.
+
+        (WebCore::RenderLayer::updatePaintingInfoForFragments):
+        (WebCore::RenderLayer::calculateClipRects):
+        * rendering/RenderLayer.h:
+        (WebCore::LayerFragment::LayerFragment):
+        (WebCore::LayerFragment::setRects):
+        (WebCore::LayerFragment::moveBy):
+        (WebCore::LayerFragment::intersect):
+        Improve the LayerFragment so that it caches transformed bounding boxes as
+        well. This is needed to fix intersectsDamageRect so that it doesn't grab
+        the wrong bounding box when checking inline layers that are paginated.
+
+        * rendering/RenderMultiColumnFlowThread.cpp:
+        (WebCore::RenderMultiColumnFlowThread::flowThreadDescendantInserted):
+        Ignore inserted flow threads inside an ancestor flow thread, since we only
+        care about what the sets do.
+        
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::insertedIntoTree):
+        Make sure that nested flow thread layers return themselves when a child
+        is inserted directly under them.
+
</ins><span class="cx"> 2014-04-22  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [OS X] Make checking if a font is the system font more robust
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlock.cpp        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -4828,6 +4828,9 @@
</span><span class="cx"> 
</span><span class="cx"> RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
</span><span class="cx"> {
</span><ins>+    if (isInFlowRenderFlowThread())
+        return 0;
+
</ins><span class="cx">     RenderFlowThread* flowThread = flowThreadContainingBlock();
</span><span class="cx">     if (!flowThread || !flowThread-&gt;hasValidRegionInfo())
</span><span class="cx">         return 0;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayer.cpp        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -4240,11 +4240,35 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RenderLayer* RenderLayer::enclosingPaginationLayerInSubtree(const RenderLayer* rootLayer) const
+{
+    // If we don't have an enclosing layer, or if the root layer is the same as the enclosing layer,
+    // then just return the enclosing pagination layer (it will be 0 in the former case and the rootLayer in the latter case).
+    if (!m_enclosingPaginationLayer || rootLayer == m_enclosingPaginationLayer)
+        return m_enclosingPaginationLayer;
+    
+    // Walk up the layer tree and see which layer we hit first. If it's the root, then the enclosing pagination
+    // layer isn't in our subtree and we return 0. If we hit the enclosing pagination layer first, then
+    // we can return it.
+    for (const RenderLayer* layer = this; layer; layer = layer-&gt;parent()) {
+        if (layer == rootLayer)
+            return 0;
+        if (layer == m_enclosingPaginationLayer)
+            return m_enclosingPaginationLayer;
+    }
+    
+    // This should never be reached, since an enclosing layer should always either be the rootLayer or be
+    // our enclosing pagination layer.
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
</ins><span class="cx"> void RenderLayer::collectFragments(LayerFragments&amp; fragments, const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect&amp; dirtyRect,
</span><span class="cx">     ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot,
</span><del>-    const LayoutRect* layerBoundingBox)
</del><ins>+    const LayoutRect* layerBoundingBox, ShouldApplyRootOffsetToFragments applyRootOffsetToFragments)
</ins><span class="cx"> {
</span><del>-    if (!enclosingPaginationLayer() || hasTransform()) {
</del><ins>+    RenderLayer* paginationLayer = enclosingPaginationLayerInSubtree(rootLayer);
+    if (!paginationLayer || hasTransform()) {
</ins><span class="cx">         // For unpaginated layers, there is only one fragment.
</span><span class="cx">         LayerFragment fragment;
</span><span class="cx">         ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
</span><span class="lines">@@ -4255,11 +4279,11 @@
</span><span class="cx">     
</span><span class="cx">     // Compute our offset within the enclosing pagination layer.
</span><span class="cx">     LayoutPoint offsetWithinPaginatedLayer;
</span><del>-    convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer);
</del><ins>+    convertToLayerCoords(paginationLayer, offsetWithinPaginatedLayer);
</ins><span class="cx">     
</span><span class="cx">     // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate
</span><span class="cx">     // layers between us and the pagination context. It's important to minimize the number of fragments we need to create and this helps with that.
</span><del>-    ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
</del><ins>+    ClipRectsContext paginationClipRectsContext(paginationLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
</ins><span class="cx">     LayoutRect layerBoundsInFlowThread;
</span><span class="cx">     ClipRect backgroundRectInFlowThread;
</span><span class="cx">     ClipRect foregroundRectInFlowThread;
</span><span class="lines">@@ -4268,9 +4292,68 @@
</span><span class="cx">         outlineRectInFlowThread, &amp;offsetWithinPaginatedLayer);
</span><span class="cx">     
</span><span class="cx">     // Take our bounding box within the flow thread and clip it.
</span><del>-    LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(enclosingPaginationLayer(), 0, &amp;offsetWithinPaginatedLayer);
</del><ins>+    LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(paginationLayer, 0, &amp;offsetWithinPaginatedLayer);
</ins><span class="cx">     layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
</span><ins>+    
+    RenderFlowThread&amp; enclosingFlowThread = toRenderFlowThread(paginationLayer-&gt;renderer());
+    RenderLayer* parentPaginationLayer = paginationLayer-&gt;parent()-&gt;enclosingPaginationLayerInSubtree(rootLayer);
+    LayerFragments ancestorFragments;
+    if (parentPaginationLayer) {
+        // Compute a bounding box accounting for fragments.
+        LayoutRect layerFragmentBoundingBoxInParentPaginationLayer = enclosingFlowThread.fragmentsBoundingBox(layerBoundingBoxInFlowThread);
+        
+        // Convert to be in the ancestor pagination context's coordinate space.
+        LayoutPoint offsetWithinParentPaginatedLayer;
+        paginationLayer-&gt;convertToLayerCoords(parentPaginationLayer, offsetWithinParentPaginatedLayer);
+        layerFragmentBoundingBoxInParentPaginationLayer.moveBy(offsetWithinParentPaginatedLayer);
+        
+        // Now collect ancestor fragments.
+        parentPaginationLayer-&gt;collectFragments(ancestorFragments, rootLayer, region, dirtyRect, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, nullptr, &amp;layerFragmentBoundingBoxInParentPaginationLayer, ApplyRootOffsetToFragments);
+        
+        if (ancestorFragments.isEmpty())
+            return;
+        
+        for (auto&amp; ancestorFragment : ancestorFragments) {
+            // Shift the dirty rect into flow thread coordinates.
+            LayoutRect dirtyRectInFlowThread(dirtyRect);
+            dirtyRectInFlowThread.moveBy(-offsetWithinParentPaginatedLayer + -ancestorFragment.paginationOffset);
+            
+            size_t oldSize = fragments.size();
+            
+            // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
+            // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box.
+            enclosingFlowThread.collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread);
+            
+            size_t newSize = fragments.size();
+            
+            if (oldSize == newSize)
+                continue;
</ins><span class="cx"> 
</span><ins>+            for (size_t i = oldSize; i &lt; newSize; ++i) {
+                LayerFragment&amp; fragment = fragments.at(i);
+                
+                // Set our four rects with all clipping applied that was internal to the flow thread.
+                fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread, &amp;layerBoundingBoxInFlowThread);
+                
+                // Shift to the root-relative physical position used when painting the flow thread in this fragment.
+                fragment.moveBy(ancestorFragment.paginationOffset + fragment.paginationOffset + offsetWithinParentPaginatedLayer);
+
+                // Intersect the fragment with our ancestor's background clip so that e.g., columns in an overflow:hidden block are
+                // properly clipped by the overflow.
+                fragment.intersect(ancestorFragment.paginationClip);
+                
+                // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column
+                // clip, so the column clip ends up being all we apply.
+                fragment.intersect(fragment.paginationClip);
+                
+                if (applyRootOffsetToFragments == ApplyRootOffsetToFragments)
+                    fragment.paginationOffset = fragment.paginationOffset + offsetWithinParentPaginatedLayer;
+            }
+        }
+        
+        return;
+    }
+    
</ins><span class="cx">     // Shift the dirty rect into flow thread coordinates.
</span><span class="cx">     LayoutPoint offsetOfPaginationLayerFromRoot;
</span><span class="cx">     enclosingPaginationLayer()-&gt;convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
</span><span class="lines">@@ -4279,7 +4362,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
</span><span class="cx">     // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box.
</span><del>-    RenderFlowThread&amp; enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()-&gt;renderer());
</del><span class="cx">     enclosingFlowThread.collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread);
</span><span class="cx">     
</span><span class="cx">     if (fragments.isEmpty())
</span><span class="lines">@@ -4287,9 +4369,9 @@
</span><span class="cx">     
</span><span class="cx">     // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents.
</span><span class="cx">     ClipRect ancestorClipRect = dirtyRect;
</span><del>-    if (enclosingPaginationLayer()-&gt;parent()) {
</del><ins>+    if (paginationLayer-&gt;parent()) {
</ins><span class="cx">         ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
</span><del>-        ancestorClipRect = enclosingPaginationLayer()-&gt;backgroundClipRect(clipRectsContext);
</del><ins>+        ancestorClipRect = paginationLayer-&gt;backgroundClipRect(clipRectsContext);
</ins><span class="cx">         ancestorClipRect.intersect(dirtyRect);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -4297,7 +4379,7 @@
</span><span class="cx">         LayerFragment&amp; fragment = fragments.at(i);
</span><span class="cx">         
</span><span class="cx">         // Set our four rects with all clipping applied that was internal to the flow thread.
</span><del>-        fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread);
</del><ins>+        fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread, &amp;layerBoundingBoxInFlowThread);
</ins><span class="cx">         
</span><span class="cx">         // Shift to the root-relative physical position used when painting the flow thread in this fragment.
</span><span class="cx">         fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
</span><span class="lines">@@ -4309,6 +4391,9 @@
</span><span class="cx">         // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column
</span><span class="cx">         // clip, so the column clip ends up being all we apply.
</span><span class="cx">         fragment.intersect(fragment.paginationClip);
</span><ins>+        
+        if (applyRootOffsetToFragments == ApplyRootOffsetToFragments)
+            fragment.paginationOffset = fragment.paginationOffset + offsetOfPaginationLayerFromRoot;
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -4321,7 +4406,7 @@
</span><span class="cx">         fragment.shouldPaintContent = shouldPaintContent;
</span><span class="cx">         if (this != localPaintingInfo.rootLayer || !(localPaintFlags &amp; PaintLayerPaintingOverflowContents)) {
</span><span class="cx">             LayoutPoint newOffsetFromRoot = *offsetFromRoot + fragment.paginationOffset;
</span><del>-            fragment.shouldPaintContent &amp;= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &amp;newOffsetFromRoot, localPaintingInfo.renderNamedFlowFragment);
</del><ins>+            fragment.shouldPaintContent &amp;= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &amp;newOffsetFromRoot, localPaintingInfo.renderNamedFlowFragment, fragment.hasBoundingBox ? &amp;fragment.boundingBox : 0);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -5650,7 +5735,7 @@
</span><span class="cx">         renderer().repaintRectangle(rect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderLayer::intersectsDamageRect(const LayoutRect&amp; layerBounds, const LayoutRect&amp; damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot, RenderRegion* region) const
</del><ins>+bool RenderLayer::intersectsDamageRect(const LayoutRect&amp; layerBounds, const LayoutRect&amp; damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot, RenderRegion* region, const LayoutRect* cachedBoundingBox) const
</ins><span class="cx"> {
</span><span class="cx">     // Always examine the canvas and the root.
</span><span class="cx">     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
</span><span class="lines">@@ -5678,9 +5763,13 @@
</span><span class="cx">         if (b.intersects(damageRect))
</span><span class="cx">             return true;
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
</span><del>-    // the damage rect.
</del><ins>+    // the damage rect. It's possible the fragment computed the bounding box already, in which case we
+    // can use the cached value.
+    if (cachedBoundingBox)
+        return cachedBoundingBox-&gt;intersects(damageRect);
+    
</ins><span class="cx">     return boundingBox(rootLayer, 0, offsetFromRoot).intersects(damageRect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -5734,26 +5823,32 @@
</span><span class="cx">         renderBox()-&gt;flipForWritingMode(result);
</span><span class="cx">     else
</span><span class="cx">         renderer().containingBlock()-&gt;flipForWritingMode(result);
</span><del>-
-    if (enclosingPaginationLayer() &amp;&amp; (flags &amp; UseFragmentBoxes)) {
</del><ins>+    
+    const RenderLayer* paginationLayer = (flags &amp; UseFragmentBoxes) ? enclosingPaginationLayerInSubtree(ancestorLayer) : 0;
+    const RenderLayer* childLayer = this;
+    bool isPaginated = paginationLayer;
+    
+    while (paginationLayer) {
</ins><span class="cx">         // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
</span><span class="cx">         // get our true bounding box.
</span><span class="cx">         LayoutPoint offsetWithinPaginationLayer;
</span><del>-        convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginationLayer);        
</del><ins>+        childLayer-&gt;convertToLayerCoords(paginationLayer, offsetWithinPaginationLayer);
</ins><span class="cx">         result.moveBy(offsetWithinPaginationLayer);
</span><span class="cx"> 
</span><del>-        RenderFlowThread&amp; enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()-&gt;renderer());
</del><ins>+        RenderFlowThread&amp; enclosingFlowThread = toRenderFlowThread(paginationLayer-&gt;renderer());
</ins><span class="cx">         result = enclosingFlowThread.fragmentsBoundingBox(result);
</span><span class="cx">         
</span><ins>+        childLayer = paginationLayer;
+        paginationLayer = paginationLayer-&gt;parent()-&gt;enclosingPaginationLayerInSubtree(ancestorLayer);
+    }
+
+    if (isPaginated) {
</ins><span class="cx">         LayoutPoint delta;
</span><del>-        if (offsetFromRoot)
-            delta = *offsetFromRoot;
-        else
-            enclosingPaginationLayer()-&gt;convertToLayerCoords(ancestorLayer, delta);
</del><ins>+        childLayer-&gt;convertToLayerCoords(ancestorLayer, delta);
</ins><span class="cx">         result.moveBy(delta);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     LayoutPoint delta;
</span><span class="cx">     if (offsetFromRoot)
</span><span class="cx">         delta = *offsetFromRoot;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayer.h (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayer.h        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/rendering/RenderLayer.h        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -236,6 +236,11 @@
</span><span class="cx">     RespectOverflowClip
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum ShouldApplyRootOffsetToFragments {
+    ApplyRootOffsetToFragments,
+    IgnoreRootOffsetForFragments
+};
+
</ins><span class="cx"> struct ClipRectsCache {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -273,14 +278,19 @@
</span><span class="cx"> public:
</span><span class="cx">     LayerFragment()
</span><span class="cx">         : shouldPaintContent(false)
</span><ins>+        , hasBoundingBox(false)
</ins><span class="cx">     { }
</span><span class="cx"> 
</span><del>-    void setRects(const LayoutRect&amp; bounds, const ClipRect&amp; background, const ClipRect&amp; foreground, const ClipRect&amp; outline)
</del><ins>+    void setRects(const LayoutRect&amp; bounds, const ClipRect&amp; background, const ClipRect&amp; foreground, const ClipRect&amp; outline, const LayoutRect* bbox)
</ins><span class="cx">     {
</span><span class="cx">         layerBounds = bounds;
</span><span class="cx">         backgroundRect = background;
</span><span class="cx">         foregroundRect = foreground;
</span><span class="cx">         outlineRect = outline;
</span><ins>+        if (bbox) {
+            boundingBox = *bbox;
+            hasBoundingBox = true;
+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void moveBy(const LayoutPoint&amp; offset)
</span><span class="lines">@@ -290,6 +300,7 @@
</span><span class="cx">         foregroundRect.moveBy(offset);
</span><span class="cx">         outlineRect.moveBy(offset);
</span><span class="cx">         paginationClip.moveBy(offset);
</span><ins>+        boundingBox.moveBy(offset);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void intersect(const LayoutRect&amp; rect)
</span><span class="lines">@@ -297,13 +308,16 @@
</span><span class="cx">         backgroundRect.intersect(rect);
</span><span class="cx">         foregroundRect.intersect(rect);
</span><span class="cx">         outlineRect.intersect(rect);
</span><ins>+        boundingBox.intersect(rect);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool shouldPaintContent;
</span><ins>+    bool hasBoundingBox;
</ins><span class="cx">     LayoutRect layerBounds;
</span><span class="cx">     ClipRect backgroundRect;
</span><span class="cx">     ClipRect foregroundRect;
</span><span class="cx">     ClipRect outlineRect;
</span><ins>+    LayoutRect boundingBox;
</ins><span class="cx">     
</span><span class="cx">     // Unique to paginated fragments. The physical translation to apply to shift the layer when painting/hit-testing.
</span><span class="cx">     LayoutPoint paginationOffset;
</span><span class="lines">@@ -696,7 +710,7 @@
</span><span class="cx">     LayoutRect localClipRect(bool&amp; clipExceedsBounds) const; // Returns the background clip rect of the layer in the local coordinate space.
</span><span class="cx"> 
</span><span class="cx">     // Pass offsetFromRoot if known.
</span><del>-    bool intersectsDamageRect(const LayoutRect&amp; layerBounds, const LayoutRect&amp; damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0, RenderRegion* = 0) const;
</del><ins>+    bool intersectsDamageRect(const LayoutRect&amp; layerBounds, const LayoutRect&amp; damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0, RenderRegion* = 0, const LayoutRect* cachedBoundingBox = 0) const;
</ins><span class="cx"> 
</span><span class="cx">     enum CalculateLayerBoundsFlag {
</span><span class="cx">         IncludeSelfTransform = 1 &lt;&lt; 0,
</span><span class="lines">@@ -933,6 +947,8 @@
</span><span class="cx"> 
</span><span class="cx">     IntSize clampScrollOffset(const IntSize&amp;) const;
</span><span class="cx"> 
</span><ins>+    RenderLayer* enclosingPaginationLayerInSubtree(const RenderLayer* rootLayer) const;
+
</ins><span class="cx">     void setNextSibling(RenderLayer* next) { m_next = next; }
</span><span class="cx">     void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
</span><span class="cx">     void setParent(RenderLayer* parent);
</span><span class="lines">@@ -984,7 +1000,7 @@
</span><span class="cx"> 
</span><span class="cx">     void collectFragments(LayerFragments&amp;, const RenderLayer* rootLayer, RenderRegion*, const LayoutRect&amp; dirtyRect,
</span><span class="cx">         ClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize,
</span><del>-        ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutRect* layerBoundingBox = 0);
</del><ins>+        ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutRect* layerBoundingBox = 0, ShouldApplyRootOffsetToFragments = IgnoreRootOffsetForFragments);
</ins><span class="cx">     void updatePaintingInfoForFragments(LayerFragments&amp;, const LayerPaintingInfo&amp;, PaintLayerFlags, bool shouldPaintContent, const LayoutPoint* offsetFromRoot);
</span><span class="cx">     void paintBackgroundForFragments(const LayerFragments&amp;, GraphicsContext*, GraphicsContext* transparencyLayerContext,
</span><span class="cx">         const LayoutRect&amp; transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&amp;, PaintBehavior, RenderObject* paintingRootForRenderer);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderMultiColumnFlowThreadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -266,7 +266,7 @@
</span><span class="cx"> 
</span><span class="cx"> void RenderMultiColumnFlowThread::flowThreadDescendantInserted(RenderObject* descendant)
</span><span class="cx"> {
</span><del>-    if (m_beingEvacuated)
</del><ins>+    if (m_beingEvacuated || descendant-&gt;isInFlowRenderFlowThread())
</ins><span class="cx">         return;
</span><span class="cx">     RenderObject* subtreeRoot = descendant;
</span><span class="cx">     for (; descendant; descendant = descendant-&gt;nextInPreOrder(subtreeRoot)) {
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (167713 => 167714)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderObject.cpp        2014-04-23 17:49:40 UTC (rev 167713)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp        2014-04-23 18:05:33 UTC (rev 167714)
</span><span class="lines">@@ -1924,8 +1924,10 @@
</span><span class="cx"> 
</span><span class="cx">     if (!isFloating() &amp;&amp; parent()-&gt;childrenInline())
</span><span class="cx">         parent()-&gt;dirtyLinesFromChangedChild(this);
</span><del>-
-    if (RenderFlowThread* flowThread = parent()-&gt;flowThreadContainingBlock())
</del><ins>+    
+    if (parent()-&gt;isRenderFlowThread())
+        toRenderFlowThread(parent())-&gt;flowThreadDescendantInserted(this);
+    else if (RenderFlowThread* flowThread = parent()-&gt;flowThreadContainingBlock())
</ins><span class="cx">         flowThread-&gt;flowThreadDescendantInserted(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>