<!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>[59784] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/59784">59784</a></dd>
<dt>Author</dt> <dd>hyatt@apple.com</dd>
<dt>Date</dt> <dd>2010-05-19 14:03:20 -0700 (Wed, 19 May 2010)</dd>
</dl>
<h3>Log Message</h3>
<pre>https://bugs.webkit.org/show_bug.cgi?id=21049, opacity and position:relative fail in multi-column layouts.
Reviewed by Oliver Hunt.
Make layers split painting across columns just as normal flow content does. This is actually very
challenging, since intermediate multicol layers can exist between a child that has to be split and
its enclosing stacking context.
In order to properly paginate layers, a bit is set on all pagination roots, i.e., layers that will get
split and thus split any descendant layers that they are also responsible for painting. For a paginated
root, we walk up the layer hierarchy and collect all intermediate multicol blocks between the child
and the enclosing stacking context.
We then recur from the outside in, applying clipping and translation as we break up the layer into strips.
Composited layers remain unsplittable and have a hacked offset still in order to be placed in the right
column.
Painting and hit testing of columns has been simplified in all of the functions to use the x position of
the column rect instead of trying to increment an x offset by adding in widths and column gaps. This
makes those functions directionality-independent (and the LTR/RTL code paths are now the same).
Fix repainting of columns as well to make sure rects are split across columns only after relative position
and transforms have been applied.
Added fast/multicol/layers-split-across-columns.html
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintColumnContents):
(WebCore::RenderBlock::adjustRectForColumns):
(WebCore::RenderBlock::adjustForColumns):
* rendering/RenderBlock.h:
* rendering/RenderBox.cpp:
(WebCore::RenderBox::computeRectForRepaint):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::updateLayerPositions):
(WebCore::RenderLayer::updatePagination):
(WebCore::RenderLayer::updateLayerPosition):
(WebCore::RenderLayer::paintLayer):
(WebCore::RenderLayer::paintList):
(WebCore::RenderLayer::paintPaginatedChildLayer):
(WebCore::RenderLayer::paintChildLayerIntoColumns):
(WebCore::RenderLayer::hitTestLayer):
(WebCore::RenderLayer::hitTestList):
(WebCore::RenderLayer::hitTestPaginatedChildLayer):
(WebCore::RenderLayer::hitTestChildLayerColumns):
* rendering/RenderLayer.h:
(WebCore::RenderLayer::):
(WebCore::RenderLayer::isPaginated):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsplatformmacfastmulticollayersinmulticolexpectedtxt">trunk/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastmulticolnestedcolumnsexpectedtxt">trunk/LayoutTests/platform/mac/fast/multicol/nested-columns-expected.txt</a></li>
<li><a href="#trunkWebCoreChangeLog">trunk/WebCore/ChangeLog</a></li>
<li><a href="#trunkWebCorerenderingRenderBlockcpp">trunk/WebCore/rendering/RenderBlock.cpp</a></li>
<li><a href="#trunkWebCorerenderingRenderBlockh">trunk/WebCore/rendering/RenderBlock.h</a></li>
<li><a href="#trunkWebCorerenderingRenderBoxcpp">trunk/WebCore/rendering/RenderBox.cpp</a></li>
<li><a href="#trunkWebCorerenderingRenderLayercpp">trunk/WebCore/rendering/RenderLayer.cpp</a></li>
<li><a href="#trunkWebCorerenderingRenderLayerh">trunk/WebCore/rendering/RenderLayer.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastmulticollayerssplitacrosscolumnshtml">trunk/LayoutTests/fast/multicol/layers-split-across-columns.html</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedchecksum">trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.checksum</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedpng">trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedtxt">trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.txt</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsfastmulticollayerssplitacrosscolumnshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/multicol/layers-split-across-columns.html (0 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/multicol/layers-split-across-columns.html (rev 0)
+++ trunk/LayoutTests/fast/multicol/layers-split-across-columns.html 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+<html>
+<head>
+<style>
+.container { display:inline-block; width:220px; }
+.multicol { -moz-column-width:100px; -webkit-column-width:100px; height:300px; border:5px solid black; -webkit-column-gap: 10px; -moz-column-gap: 10px }
+.block { width:100px; height:100px }
+.block:hover { background-color: maroon !important; }
+.layer { height:400px; width:100px }
+</style>
+<body>
+
+<div class="container">
+Overflow:
+<div class="multicol">
+<div class="block" style="display:inline-block; background-color:black"></div>
+<div style="overflow:hidden;" class="layer">
+<div class="block" style="background-color: #0000f0"></div>
+<div class="block" style="background-color: #0000d0"></div>
+<div class="block" style="background-color: #0000b0"></div>
+<div class="block" style="background-color: #000090"></div>
+</div>
+<div class="block" style="display:inline-block; background-color:black"></div>
+</div>
+</div>
+
+<div class="container">
+Transforms:
+
+<div class="multicol">
+<div class="block" style="display:inline-block; background-color:black"></div>
+<div style="margin-left: -100px; -webkit-transform: translate(100px, 0);" class="layer">
+<div class="block" style="background-color: #0000f0"></div>
+<div class="block" style="background-color: #0000d0"></div>
+<div class="block" style="background-color: #0000b0"></div>
+<div class="block" style="background-color: #000090"></div>
+</div>
+<div class="block" style="display:inline-block; background-color:black"></div>
+</div>
+</div>
+</div>
+
+<div class="container">
+Relative Positioning:
+<div class="multicol">
+<div class="block" style="display:inline-block; background-color:black"></div>
+<div style="position:relative; margin-left:-100px; left:100px" class="layer">
+<div class="block" style="background-color: #0000f0"></div>
+<div class="block" style="background-color: #0000d0"></div>
+<div class="block" style="background-color: #0000b0"></div>
+<div class="block" style="background-color: #000090"></div>
+</div>
+<div class="block" style="display:inline-block; background-color:black"></div>
+</div>
+</div>
+
+<div class="container">
+Opacity:
+
+<div class="multicol">
+<div class="block" style="display:inline-block; background-color:black"></div>
+<div style="opacity:0.99;" class="layer">
+<div class="block" style="background-color: #0000f0"></div>
+<div class="block" style="background-color: #0000d0"></div>
+<div class="block" style="background-color: #0000b0"></div>
+<div class="block" style="background-color: #000090"></div>
+</div>
+<div class="block" style="display:inline-block; background-color:black"></div>
+</div>
+</div>
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastmulticollayersinmulticolexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.txt (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.txt 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/LayoutTests/platform/mac/fast/multicol/layers-in-multicol-expected.txt 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -349,21 +349,7 @@
</span><span class="cx"> RenderText {#text} at (136,234) size 106x18
</span><span class="cx"> text run at (136,234) width 106: "This is some text"
</span><span class="cx"> RenderBR {BR} at (136,248) size 0x0
</span><del>-layer at (271,31) size 100x270
</del><ins>+layer at (13,265) size 100x270
</ins><span class="cx"> RenderBlock (relative positioned) {DIV} at (0,0) size 100x270 [bgcolor=#008000]
</span><del>-layer at (787,-275) size 183x18 backgroundClip at (0,0) size 1287x672 clip at (0,0) size 1287x672 outlineClip at (0,0) size 1287x672
- RenderInline {SPAN} at (0,0) size 183x18
- RenderText {#text} at (0,486) size 183x18
- text run at (0,486) width 183: "This is some transparent text."
- RenderBR {BR} at (183,500) size 0x0
-layer at (797,229) size 242x18
- RenderBlock (relative positioned) {DIV} at (5,1013) size 242x18
- RenderText {#text} at (0,0) size 192x18
- text run at (0,0) width 192: "This is relative positioned text."
-layer at (414,359) size 100x270
</del><ins>+layer at (155,593) size 100x270 backgroundClip at (0,0) size 1287x672 clip at (0,0) size 1287x672 outlineClip at (0,0) size 1287x672
</ins><span class="cx"> RenderBlock (relative positioned) {DIV} at (142,0) size 100x270 [bgcolor=#008000]
</span><del>-layer at (-234,557) size 242x18 backgroundClip at (0,0) size 1287x672 clip at (0,0) size 1287x672 outlineClip at (0,0) size 1287x672
- RenderBlock (relative positioned) {DIV} at (5,1013) size 242x18
- RenderText {#text} at (50,0) size 192x18
- text run at (50,0) width 4 RTL: "."
- text run at (54,0) width 188: "This is relative positioned text"
</del></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedchecksum"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.checksum (0 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.checksum (rev 0)
+++ trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.checksum 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+5d5a6b56e674486e116c9f67b60865d9
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedpng"></a>
<div class="binary"><h4>Added: trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.png
</span><span class="cx">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="trunkLayoutTestsplatformmacfastmulticollayerssplitacrosscolumnsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.txt (0 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac/fast/multicol/layers-split-across-columns-expected.txt 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+layer at (0,0) size 785x676
+ RenderView at (0,0) size 785x600
+layer at (0,0) size 785x676
+ RenderBlock {HTML} at (0,0) size 785x676
+ RenderBody {BODY} at (8,8) size 769x660
+ RenderBlock {DIV} at (0,0) size 220x328
+ RenderBlock (anonymous) at (0,0) size 220x18
+ RenderText {#text} at (0,0) size 65x18
+ text run at (0,0) width 65: "Overflow:"
+ RenderText {#text} at (220,314) size 4x18
+ text run at (220,314) width 4: " "
+ RenderBlock {DIV} at (224,0) size 220x328
+ RenderBlock (anonymous) at (0,0) size 220x18
+ RenderText {#text} at (0,0) size 76x18
+ text run at (0,0) width 76: "Transforms:"
+ RenderText {#text} at (444,314) size 4x18
+ text run at (444,314) width 4: " "
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (448,0) size 220x328
+ RenderBlock (anonymous) at (0,0) size 220x18
+ RenderText {#text} at (0,0) size 131x18
+ text run at (0,0) width 131: "Relative Positioning:"
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,332) size 220x328
+ RenderBlock (anonymous) at (0,0) size 220x18
+ RenderText {#text} at (0,0) size 54x18
+ text run at (0,0) width 54: "Opacity:"
+layer at (8,26) size 220x310
+ RenderBlock {DIV} at (0,18) size 220x310 [border: (5px solid #000000)]
+ RenderBlock (anonymous) at (5,5) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock (anonymous) at (5,505) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+layer at (13,131) size 100x400
+ RenderBlock {DIV} at (5,105) size 100x400
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#0000F0]
+ RenderBlock {DIV} at (0,100) size 100x100 [bgcolor=#0000D0]
+ RenderBlock {DIV} at (0,200) size 100x100 [bgcolor=#0000B0]
+ RenderBlock {DIV} at (0,300) size 100x100 [bgcolor=#000090]
+layer at (232,26) size 220x310
+ RenderBlock {DIV} at (0,18) size 220x310 [border: (5px solid #000000)]
+ RenderBlock (anonymous) at (5,5) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock (anonymous) at (5,505) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+layer at (456,26) size 220x310
+ RenderBlock {DIV} at (0,18) size 220x310 [border: (5px solid #000000)]
+ RenderBlock (anonymous) at (5,5) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock (anonymous) at (5,505) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+layer at (8,358) size 220x310
+ RenderBlock {DIV} at (0,18) size 220x310 [border: (5px solid #000000)]
+ RenderBlock (anonymous) at (5,5) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock (anonymous) at (5,505) size 100x100
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#000000]
+ RenderText {#text} at (0,0) size 0x0
+layer at (137,131) size 100x400
+ RenderBlock {DIV} at (-95,105) size 100x400
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#0000F0]
+ RenderBlock {DIV} at (0,100) size 100x100 [bgcolor=#0000D0]
+ RenderBlock {DIV} at (0,200) size 100x100 [bgcolor=#0000B0]
+ RenderBlock {DIV} at (0,300) size 100x100 [bgcolor=#000090]
+layer at (461,131) size 100x400
+ RenderBlock (relative positioned) {DIV} at (-95,105) size 100x400
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#0000F0]
+ RenderBlock {DIV} at (0,100) size 100x100 [bgcolor=#0000D0]
+ RenderBlock {DIV} at (0,200) size 100x100 [bgcolor=#0000B0]
+ RenderBlock {DIV} at (0,300) size 100x100 [bgcolor=#000090]
+layer at (13,463) size 100x400 backgroundClip at (0,0) size 785x676 clip at (0,0) size 785x676 outlineClip at (0,0) size 785x676
+ RenderBlock {DIV} at (5,105) size 100x400
+ RenderBlock {DIV} at (0,0) size 100x100 [bgcolor=#0000F0]
+ RenderBlock {DIV} at (0,100) size 100x100 [bgcolor=#0000D0]
+ RenderBlock {DIV} at (0,200) size 100x100 [bgcolor=#0000B0]
+ RenderBlock {DIV} at (0,300) size 100x100 [bgcolor=#000090]
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastmulticolnestedcolumnsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/fast/multicol/nested-columns-expected.txt (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/multicol/nested-columns-expected.txt 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/LayoutTests/platform/mac/fast/multicol/nested-columns-expected.txt 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -48,35 +48,3 @@
</span><span class="cx"> text run at (0,18) width 154: "Nulla varius enim ac mi."
</span><span class="cx"> RenderText {#text} at (0,0) size 0x0
</span><span class="cx"> RenderText {#text} at (0,0) size 0x0
</span><del>-layer at (391,123) size 367x216
- RenderBlock {DIV} at (0,612) size 367x216
- RenderText {#text} at (0,0) size 175x396
- text run at (0,0) width 139: "Lorem ipsum dolor sit"
- text run at (0,18) width 116: "amet, consectetuer"
- text run at (0,36) width 172: "adipiscing elit. Nulla varius"
- text run at (0,54) width 137: "enim ac mi. Curabitur"
- text run at (0,72) width 173: "sollicitudin felis quis lectus."
- text run at (0,90) width 175: "Quisque adipiscing rhoncus"
- text run at (0,108) width 145: "sem. Proin nulla purus,"
- text run at (0,126) width 147: "vulputate vel, varius ut,"
- text run at (0,144) width 164: "euismod et, nisi. Sed vitae"
- text run at (0,162) width 124: "felis vel orci sagittis"
- text run at (0,180) width 147: "aliquam. Cras convallis"
- text run at (0,198) width 132: "adipiscing sem. Nam"
- text run at (0,216) width 154: "nonummy enim. Nullam"
- text run at (0,234) width 160: "bibendum lobortis neque."
- text run at (0,252) width 136: "Vestibulum velit orci,"
- text run at (0,270) width 158: "tempus euismod, pretium"
- text run at (0,288) width 167: "quis, interdum vitae, nulla."
- text run at (0,306) width 172: "Phasellus eget ante et tortor"
- text run at (0,324) width 163: "condimentum vestibulum."
- text run at (0,342) width 137: "Suspendisse hendrerit"
- text run at (0,360) width 165: "quam nec felis. Sed varius"
- text run at (0,378) width 111: "turpis vitae pede. "
- RenderText {#text} at (0,0) size 0x0
-layer at (582,-93) size 173x54 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600 outlineClip at (0,0) size 800x600
- RenderInline (relative positioned) {SPAN} at (0,0) size 173x54
- RenderText {#text} at (111,378) size 173x54
- text run at (111,378) width 42: "Lorem"
- text run at (0,396) width 131: "ipsum dolor sit amet,"
- text run at (0,414) width 173: "consectetuer adipiscing elit."
</del></span></pre></div>
<a id="trunkWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/ChangeLog (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/ChangeLog 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/ChangeLog 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2010-05-18 David Hyatt <hyatt@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ https://bugs.webkit.org/show_bug.cgi?id=21049, opacity and position:relative fail in multi-column layouts.
+
+ Make layers split painting across columns just as normal flow content does. This is actually very
+ challenging, since intermediate multicol layers can exist between a child that has to be split and
+ its enclosing stacking context.
+
+ In order to properly paginate layers, a bit is set on all pagination roots, i.e., layers that will get
+ split and thus split any descendant layers that they are also responsible for painting. For a paginated
+ root, we walk up the layer hierarchy and collect all intermediate multicol blocks between the child
+ and the enclosing stacking context.
+
+ We then recur from the outside in, applying clipping and translation as we break up the layer into strips.
+
+ Composited layers remain unsplittable and have a hacked offset still in order to be placed in the right
+ column.
+
+ Painting and hit testing of columns has been simplified in all of the functions to use the x position of
+ the column rect instead of trying to increment an x offset by adding in widths and column gaps. This
+ makes those functions directionality-independent (and the LTR/RTL code paths are now the same).
+
+ Fix repainting of columns as well to make sure rects are split across columns only after relative position
+ and transforms have been applied.
+
+ Added fast/multicol/layers-split-across-columns.html
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::paintColumnContents):
+ (WebCore::RenderBlock::adjustRectForColumns):
+ (WebCore::RenderBlock::adjustForColumns):
+ * rendering/RenderBlock.h:
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::computeRectForRepaint):
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::RenderLayer):
+ (WebCore::RenderLayer::updateLayerPositions):
+ (WebCore::RenderLayer::updatePagination):
+ (WebCore::RenderLayer::updateLayerPosition):
+ (WebCore::RenderLayer::paintLayer):
+ (WebCore::RenderLayer::paintList):
+ (WebCore::RenderLayer::paintPaginatedChildLayer):
+ (WebCore::RenderLayer::paintChildLayerIntoColumns):
+ (WebCore::RenderLayer::hitTestLayer):
+ (WebCore::RenderLayer::hitTestList):
+ (WebCore::RenderLayer::hitTestPaginatedChildLayer):
+ (WebCore::RenderLayer::hitTestChildLayerColumns):
+ * rendering/RenderLayer.h:
+ (WebCore::RenderLayer::):
+ (WebCore::RenderLayer::isPaginated):
+
</ins><span class="cx"> 2010-05-18 Dirk Pranke <dpranke@chromium.org>
</span><span class="cx">
</span><span class="cx"> Reviewed by Dimitri Glazkov.
</span></span></pre></div>
<a id="trunkWebCorerenderingRenderBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/rendering/RenderBlock.cpp (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/rendering/RenderBlock.cpp 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/rendering/RenderBlock.cpp 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -1605,24 +1605,27 @@
</span><span class="cx"> // For each rect, we clip to the rect, and then we adjust our coords.
</span><span class="cx"> IntRect colRect = colRects->at(i);
</span><span class="cx"> colRect.move(tx, ty);
</span><del>- context->save();
-
- // Each strip pushes a clip, since column boxes are specified as being
- // like overflow:hidden.
- context->clip(colRect);
-
- // Adjust tx and ty to change where we paint.
</del><span class="cx"> PaintInfo info(paintInfo);
</span><span class="cx"> info.rect.intersect(colRect);
</span><span class="cx">
</span><del>- // Adjust our x and y when painting.
- int finalX = tx + currXOffset;
- int finalY = ty + currYOffset;
- if (paintingFloats)
- paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
- else
- paintContents(info, finalX, finalY);
</del><ins>+ if (!info.rect.isEmpty()) {
+ context->save();
+
+ // Each strip pushes a clip, since column boxes are specified as being
+ // like overflow:hidden.
+ context->clip(colRect);
+
+ // Adjust our x and y when painting.
+ int finalX = tx + currXOffset;
+ int finalY = ty + currYOffset;
+ if (paintingFloats)
+ paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
+ else
+ paintContents(info, finalX, finalY);
</ins><span class="cx">
</span><ins>+ context->restore();
+ }
+
</ins><span class="cx"> // Move to the next position.
</span><span class="cx"> if (style()->direction() == LTR)
</span><span class="cx"> currXOffset += colRect.width() + colGap;
</span><span class="lines">@@ -1630,8 +1633,6 @@
</span><span class="cx"> currXOffset -= (colRect.width() + colGap);
</span><span class="cx">
</span><span class="cx"> currYOffset -= colRect.height();
</span><del>-
- context->restore();
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3370,17 +3371,19 @@
</span><span class="cx"> bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
</span><span class="cx"> {
</span><span class="cx"> // We need to do multiple passes, breaking up our hit testing into strips.
</span><del>- // We can always go left to right, since column contents are clipped (meaning that there
- // can't be any overlap).
</del><span class="cx"> Vector<IntRect>* colRects = columnRects();
</span><del>- unsigned colCount = colRects->size();
</del><ins>+ int colCount = colRects->size();
</ins><span class="cx"> if (!colCount)
</span><span class="cx"> return false;
</span><del>- int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width();
</del><ins>+ int left = borderLeft() + paddingLeft();
</ins><span class="cx"> int currYOffset = 0;
</span><del>- int colGap = columnGap();
- for (unsigned i = 0; i < colCount; i++) {
</del><ins>+ int i;
+ for (i = 0; i < colCount; i++)
+ currYOffset -= colRects->at(i).height();
+ for (i = colCount - 1; i >= 0; i--) {
</ins><span class="cx"> IntRect colRect = colRects->at(i);
</span><ins>+ int currXOffset = colRect.x() - left;
+ currYOffset += colRect.height();
</ins><span class="cx"> colRect.move(tx, ty);
</span><span class="cx">
</span><span class="cx"> if (colRect.contains(x, y)) {
</span><span class="lines">@@ -3391,14 +3394,6 @@
</span><span class="cx"> int finalY = ty + currYOffset;
</span><span class="cx"> return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
</span><span class="cx"> }
</span><del>-
- // Move to the next position.
- if (style()->direction() == LTR)
- currXOffset += colRect.width() + colGap;
- else
- currXOffset -= (colRect.width() + colGap);
-
- currYOffset -= colRect.height();
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return false;
</span><span class="lines">@@ -3903,11 +3898,13 @@
</span><span class="cx"> unsigned colCount = colRects->size();
</span><span class="cx"> if (!colCount)
</span><span class="cx"> return;
</span><del>- int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - colRects->at(0).width();
</del><ins>+
+ int left = borderLeft() + paddingLeft();
+
</ins><span class="cx"> int currYOffset = 0;
</span><del>- int colGap = columnGap();
</del><span class="cx"> for (unsigned i = 0; i < colCount; i++) {
</span><span class="cx"> IntRect colRect = colRects->at(i);
</span><ins>+ int currXOffset = colRect.x() - left;
</ins><span class="cx">
</span><span class="cx"> IntRect repaintRect = r;
</span><span class="cx"> repaintRect.move(currXOffset, currYOffset);
</span><span class="lines">@@ -3917,11 +3914,6 @@
</span><span class="cx"> result.unite(repaintRect);
</span><span class="cx">
</span><span class="cx"> // Move to the next position.
</span><del>- if (style()->direction() == LTR)
- currXOffset += colRect.width() + colGap;
- else
- currXOffset -= (colRect.width() + colGap);
-
</del><span class="cx"> currYOffset -= colRect.height();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3934,23 +3926,18 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> Vector<IntRect>& columnRects = *this->columnRects();
</span><del>-
- int gapWidth = columnGap();
-
- int xOffset = style()->direction() == LTR ? 0 : contentWidth() - columnRects[0].width();
</del><ins>+
+ int left = borderLeft() + paddingLeft();
</ins><span class="cx"> int yOffset = 0;
</span><span class="cx"> size_t columnCount = columnRects.size();
</span><span class="cx"> for (size_t i = 0; i < columnCount; ++i) {
</span><span class="cx"> IntRect columnRect = columnRects[i];
</span><ins>+ int xOffset = columnRect.x() - left;
</ins><span class="cx"> if (point.y() < columnRect.bottom() + yOffset) {
</span><span class="cx"> offset.expand(xOffset, -yOffset);
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (style()->direction() == LTR)
- xOffset += columnRect.width() + gapWidth;
- else
- xOffset -= columnRect.width() + gapWidth;
</del><span class="cx"> yOffset += columnRect.height();
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebCorerenderingRenderBlockh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/rendering/RenderBlock.h (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/rendering/RenderBlock.h 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/rendering/RenderBlock.h 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -143,6 +143,9 @@
</span><span class="cx"> static void appendRunsForObject(int start, int end, RenderObject*, InlineBidiResolver&);
</span><span class="cx"> static bool requiresLineBox(const InlineIterator&, bool isLineEmpty = true, bool previousLineBrokeCleanly = true);
</span><span class="cx">
</span><ins>+ Vector<IntRect>* columnRects() const;
+ int columnGap() const;
+
</ins><span class="cx"> protected:
</span><span class="cx"> void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child);
</span><span class="cx"> void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child);
</span><span class="lines">@@ -200,7 +203,7 @@
</span><span class="cx">
</span><span class="cx"> virtual bool hasLineIfEmpty() const;
</span><span class="cx"> bool layoutOnlyPositionedObjects();
</span><del>-
</del><ins>+
</ins><span class="cx"> private:
</span><span class="cx"> virtual RenderObjectChildList* virtualChildren() { return children(); }
</span><span class="cx"> virtual const RenderObjectChildList* virtualChildren() const { return children(); }
</span><span class="lines">@@ -348,10 +351,8 @@
</span><span class="cx">
</span><span class="cx"> int desiredColumnWidth() const;
</span><span class="cx"> unsigned desiredColumnCount() const;
</span><del>- Vector<IntRect>* columnRects() const;
</del><span class="cx"> void setDesiredColumnCountAndWidth(int count, int width);
</span><del>- int columnGap() const;
-
</del><ins>+
</ins><span class="cx"> void paintContinuationOutlines(PaintInfo&, int tx, int ty);
</span><span class="cx">
</span><span class="cx"> virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
</span></span></pre></div>
<a id="trunkWebCorerenderingRenderBoxcpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/rendering/RenderBox.cpp (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/rendering/RenderBox.cpp 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/rendering/RenderBox.cpp 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -1188,22 +1188,11 @@
</span><span class="cx">
</span><span class="cx"> EPosition position = style()->position();
</span><span class="cx">
</span><del>- if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) {
- RenderBlock* cb = toRenderBlock(o);
- if (cb->hasColumns()) {
- IntRect repaintRect(topLeft, rect.size());
- cb->adjustRectForColumns(repaintRect);
- topLeft = repaintRect.location();
- rect = repaintRect;
- }
- }
-
</del><span class="cx"> // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box
</span><span class="cx"> // in the parent's coordinate space that encloses us.
</span><span class="cx"> if (layer() && layer()->transform()) {
</span><span class="cx"> fixed = position == FixedPosition;
</span><span class="cx"> rect = layer()->transform()->mapRect(rect);
</span><del>- // FIXME: this clobbers topLeft adjustment done for multicol above
</del><span class="cx"> topLeft = rect.location();
</span><span class="cx"> topLeft.move(x(), y());
</span><span class="cx"> } else if (position == FixedPosition)
</span><span class="lines">@@ -1219,6 +1208,16 @@
</span><span class="cx"> topLeft += layer()->relativePositionOffset();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (o->isBlockFlow() && position != AbsolutePosition && position != FixedPosition) {
+ RenderBlock* cb = toRenderBlock(o);
+ if (cb->hasColumns()) {
+ IntRect repaintRect(topLeft, rect.size());
+ cb->adjustRectForColumns(repaintRect);
+ topLeft = repaintRect.location();
+ rect = repaintRect;
+ }
+ }
+
</ins><span class="cx"> // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
</span><span class="cx"> // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
</span><span class="cx"> if (o->hasOverflowClip()) {
</span></span></pre></div>
<a id="trunkWebCorerenderingRenderLayercpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/rendering/RenderLayer.cpp (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/rendering/RenderLayer.cpp 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/rendering/RenderLayer.cpp 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -166,6 +166,7 @@
</span><span class="cx"> , m_hasVisibleContent(false)
</span><span class="cx"> , m_visibleDescendantStatusDirty(false)
</span><span class="cx"> , m_hasVisibleDescendant(false)
</span><ins>+ , m_isPaginated(false)
</ins><span class="cx"> , m_3DTransformedDescendantStatusDirty(true)
</span><span class="cx"> , m_has3DTransformedDescendant(false)
</span><span class="cx"> #if USE(ACCELERATED_COMPOSITING)
</span><span class="lines">@@ -308,7 +309,12 @@
</span><span class="cx"> updateVisibilityStatus();
</span><span class="cx">
</span><span class="cx"> updateTransform();
</span><del>-
</del><ins>+
+ if (flags & UpdatePagination)
+ updatePagination();
+ else
+ m_isPaginated = false;
+
</ins><span class="cx"> if (m_hasVisibleContent) {
</span><span class="cx"> RenderView* view = renderer()->view();
</span><span class="cx"> ASSERT(view);
</span><span class="lines">@@ -351,6 +357,9 @@
</span><span class="cx"> flags &= ~IsCompositingUpdateRoot;
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ if (renderer()->hasColumns())
+ flags |= UpdatePagination;
+
</ins><span class="cx"> for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
</span><span class="cx"> child->updateLayerPositions(flags, cachedOffset);
</span><span class="cx">
</span><span class="lines">@@ -449,6 +458,30 @@
</span><span class="cx"> return *m_transform;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void RenderLayer::updatePagination()
+{
+ m_isPaginated = false;
+ if (isComposited() || !parent() || renderer()->isPositioned())
+ return; // FIXME: We will have to deal with paginated compositing layers someday.
+ // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though.
+
+ if (isNormalFlowOnly()) {
+ m_isPaginated = parent()->renderer()->hasColumns();
+ return;
+ }
+
+ // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context.
+ RenderLayer* ancestorStackingContext = stackingContext();
+ for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+ if (curr->renderer()->hasColumns()) {
+ m_isPaginated = true;
+ return;
+ }
+ if (curr == ancestorStackingContext || (curr->parent() && curr->parent()->renderer()->isPositioned()))
+ return;
+ }
+}
+
</ins><span class="cx"> void RenderLayer::setHasVisibleContent(bool b)
</span><span class="cx"> {
</span><span class="cx"> if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
</span><span class="lines">@@ -644,10 +677,14 @@
</span><span class="cx"> localPoint += offset;
</span><span class="cx"> }
</span><span class="cx"> } else if (parent()) {
</span><del>- IntSize columnOffset;
- parent()->renderer()->adjustForColumns(columnOffset, localPoint);
- localPoint += columnOffset;
-
</del><ins>+ if (isComposited()) {
+ // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
+ // They won't split across columns properly.
+ IntSize columnOffset;
+ parent()->renderer()->adjustForColumns(columnOffset, localPoint);
+ localPoint += columnOffset;
+ }
+
</ins><span class="cx"> IntSize scrollOffset = parent()->scrolledContentOffset();
</span><span class="cx"> localPoint -= scrollOffset;
</span><span class="cx"> }
</span><span class="lines">@@ -2376,10 +2413,8 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Now walk the sorted list of children with negative z-indices.
</span><del>- if (m_negZOrderList)
- for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
-
</del><ins>+ paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
+
</ins><span class="cx"> // Now establish the appropriate clip and paint our child RenderObjects.
</span><span class="cx"> if (shouldPaint && !clipRectToApply.isEmpty()) {
</span><span class="cx"> // Begin transparency layers lazily now that we know we have to paint something.
</span><span class="lines">@@ -2415,15 +2450,11 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Paint any child layers that have overflow.
</span><del>- if (m_normalFlowList)
- for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
-
</del><ins>+ paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
+
</ins><span class="cx"> // Now walk the sorted list of children with positive z-indices.
</span><del>- if (m_posZOrderList)
- for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
-
</del><ins>+ paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
+
</ins><span class="cx"> if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
</span><span class="cx"> setClip(p, paintDirtyRect, damageRect);
</span><span class="cx">
</span><span class="lines">@@ -2443,6 +2474,119 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p,
+ const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
+ PaintLayerFlags paintFlags)
+{
+ if (!list)
+ return;
+
+ for (size_t i = 0; i < list->size(); ++i) {
+ RenderLayer* childLayer = list->at(i);
+ if (!childLayer->isPaginated())
+ childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
+ else
+ paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
+ }
+}
+
+void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
+ const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
+ PaintLayerFlags paintFlags)
+{
+ // We need to do multiple passes, breaking up our child layer into strips.
+ ASSERT(!renderer()->isPositioned());
+ Vector<RenderLayer*> columnLayers;
+ RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
+ for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
+ if (curr->renderer()->hasColumns())
+ columnLayers.append(curr);
+ if (curr == ancestorLayer || (curr->parent() && curr->parent()->renderer()->isPositioned()))
+ break;
+ }
+
+ ASSERT(columnLayers.size());
+
+ paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1);
+}
+
+void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
+ const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
+ PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
+{
+ RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
+
+ ASSERT(columnBlock && columnBlock->hasColumns());
+ if (!columnBlock || !columnBlock->hasColumns())
+ return;
+
+ int layerX = 0;
+ int layerY = 0;
+ columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
+
+ Vector<IntRect>* colRects = columnBlock->columnRects();
+ unsigned colCount = colRects->size();
+ int currYOffset = 0;
+ for (unsigned i = 0; i < colCount; i++) {
+ // For each rect, we clip to the rect, and then we adjust our coords.
+ IntRect colRect = colRects->at(i);
+ int currXOffset = colRect.x() - (columnBlock->borderLeft() + columnBlock->paddingLeft());
+ colRect.move(layerX, layerY);
+
+ IntRect localDirtyRect(paintDirtyRect);
+ localDirtyRect.intersect(colRect);
+
+ if (!localDirtyRect.isEmpty()) {
+ context->save();
+
+ // Each strip pushes a clip, since column boxes are specified as being
+ // like overflow:hidden.
+ context->clip(colRect);
+
+ if (!colIndex) {
+ // Apply a translation transform to change where the layer paints.
+ TransformationMatrix oldTransform;
+ bool oldHasTransform = childLayer->transform();
+ if (oldHasTransform)
+ oldTransform = *childLayer->transform();
+ TransformationMatrix newTransform(oldTransform);
+ newTransform.translateRight(currXOffset, currYOffset);
+
+ childLayer->m_transform.set(new TransformationMatrix(newTransform));
+ childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
+ if (oldHasTransform)
+ childLayer->m_transform.set(new TransformationMatrix(oldTransform));
+ else
+ childLayer->m_transform.clear();
+ } else {
+ // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
+ // This involves subtracting out the position of the layer in our current coordinate space.
+ int childX = 0;
+ int childY = 0;
+ columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY);
+ TransformationMatrix transform;
+ transform.translateRight(childX + currXOffset, childY + currYOffset);
+
+ // Apply the transform.
+ context->concatCTM(transform.toAffineTransform());
+
+ // Now do a paint with the root layer shifted to be the next multicol block.
+ paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior,
+ paintingRoot, overlapTestRequests, paintFlags,
+ columnLayers, colIndex - 1);
+ }
+
+ context->restore();
+ }
+
+ // Move to the next position.
+ currYOffset -= colRect.height();
+ }
+}
+
</ins><span class="cx"> static inline IntRect frameVisibleRect(RenderObject* renderer)
</span><span class="cx"> {
</span><span class="cx"> FrameView* frameView = renderer->document()->view();
</span><span class="lines">@@ -2575,8 +2719,8 @@
</span><span class="cx"> // If zOffset is non-null (which indicates that the caller wants z offset information),
</span><span class="cx"> // *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
</span><span class="cx"> RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
</span><del>- const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
- const HitTestingTransformState* transformState, double* zOffset)
</del><ins>+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
+ const HitTestingTransformState* transformState, double* zOffset)
</ins><span class="cx"> {
</span><span class="cx"> // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
</span><span class="cx">
</span><span class="lines">@@ -2686,34 +2830,21 @@
</span><span class="cx"> RenderLayer* candidateLayer = 0;
</span><span class="cx">
</span><span class="cx"> // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
</span><del>- if (m_posZOrderList) {
- for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
- HitTestResult tempResult(result.point());
- RenderLayer* hitLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
- if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
- result = tempResult;
- if (!depthSortDescendants)
- return hitLayer;
-
- candidateLayer = hitLayer;
- }
- }
</del><ins>+ RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+ if (hitLayer) {
+ if (!depthSortDescendants)
+ return hitLayer;
+ candidateLayer = hitLayer;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Now check our overflow objects.
</span><del>- if (m_normalFlowList) {
- for (int i = m_normalFlowList->size() - 1; i >= 0; --i) {
- RenderLayer* currLayer = m_normalFlowList->at(i);
- HitTestResult tempResult(result.point());
- RenderLayer* hitLayer = currLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
- if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
- result = tempResult;
- if (!depthSortDescendants)
- return hitLayer;
-
- candidateLayer = hitLayer;
- }
- }
</del><ins>+ hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+ if (hitLayer) {
+ if (!depthSortDescendants)
+ return hitLayer;
+ candidateLayer = hitLayer;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
</span><span class="lines">@@ -2731,20 +2862,14 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Now check our negative z-index children.
</span><del>- if (m_negZOrderList) {
- for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
- HitTestResult tempResult(result.point());
- RenderLayer* hitLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
- if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
- result = tempResult;
- if (!depthSortDescendants)
- return hitLayer;
</del><ins>+ hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
+ localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+ if (hitLayer) {
+ if (!depthSortDescendants)
+ return hitLayer;
+ candidateLayer = hitLayer;
+ }
</ins><span class="cx">
</span><del>- candidateLayer = hitLayer;
- }
- }
- }
-
</del><span class="cx"> // If we found a layer, return. Child layers, and foreground always render in front of background.
</span><span class="cx"> if (candidateLayer)
</span><span class="cx"> return candidateLayer;
</span><span class="lines">@@ -2787,6 +2912,127 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
+ const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* transformState,
+ double* zOffsetForDescendants, double* zOffset,
+ const HitTestingTransformState* unflattenedTransformState,
+ bool depthSortDescendants)
+{
+ if (!list)
+ return 0;
+
+ RenderLayer* resultLayer = 0;
+ for (int i = list->size() - 1; i >= 0; --i) {
+ RenderLayer* childLayer = list->at(i);
+ RenderLayer* hitLayer = 0;
+ HitTestResult tempResult(result.point());
+ if (childLayer->isPaginated())
+ hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
+ else
+ hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
+ if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
+ resultLayer = hitLayer;
+ result = tempResult;
+ if (!depthSortDescendants)
+ break;
+ }
+ }
+
+ return resultLayer;
+}
+
+RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset)
+{
+ ASSERT(!renderer()->isPositioned());
+ Vector<RenderLayer*> columnLayers;
+ RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
+ for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
+ if (curr->renderer()->hasColumns())
+ columnLayers.append(curr);
+ if (curr == ancestorLayer || (curr->parent() && curr->parent()->renderer()->isPositioned()))
+ break;
+ }
+
+ ASSERT(columnLayers.size());
+ return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset,
+ columnLayers, columnLayers.size() - 1);
+}
+
+RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset,
+ const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
+{
+ RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
+
+ ASSERT(columnBlock && columnBlock->hasColumns());
+ if (!columnBlock || !columnBlock->hasColumns())
+ return 0;
+
+ int layerX = 0;
+ int layerY = 0;
+ columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
+
+ Vector<IntRect>* colRects = columnBlock->columnRects();
+ int colCount = colRects->size();
+
+ // We have to go backwards from the last column to the first.
+ int left = columnBlock->borderLeft() + columnBlock->paddingLeft();
+ int currYOffset = 0;
+ int i;
+ for (i = 0; i < colCount; i++)
+ currYOffset -= colRects->at(i).height();
+ for (i = colCount - 1; i >= 0; i--) {
+ // For each rect, we clip to the rect, and then we adjust our coords.
+ IntRect colRect = colRects->at(i);
+ int currXOffset = colRect.x() - left;
+ currYOffset += colRect.height();
+ colRect.move(layerX, layerY);
+
+ IntRect localClipRect(hitTestRect);
+ localClipRect.intersect(colRect);
+
+ if (!localClipRect.isEmpty() && localClipRect.contains(hitTestPoint)) {
+ RenderLayer* hitLayer = 0;
+ if (!columnIndex) {
+ // Apply a translation transform to change where the layer paints.
+ TransformationMatrix oldTransform;
+ bool oldHasTransform = childLayer->transform();
+ if (oldHasTransform)
+ oldTransform = *childLayer->transform();
+ TransformationMatrix newTransform(oldTransform);
+ newTransform.translateRight(currXOffset, currYOffset);
+
+ childLayer->m_transform.set(new TransformationMatrix(newTransform));
+ hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
+ if (oldHasTransform)
+ childLayer->m_transform.set(new TransformationMatrix(oldTransform));
+ else
+ childLayer->m_transform.clear();
+ } else {
+ // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
+ // This involves subtracting out the position of the layer in our current coordinate space.
+ RenderLayer* nextLayer = columnLayers[columnIndex - 1];
+ RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState);
+ newTransformState->translate(currXOffset, currYOffset, HitTestingTransformState::AccumulateTransform);
+ IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
+ IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
+ newTransformState->flatten();
+
+ hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint,
+ newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
+ }
+
+ if (hitLayer)
+ return hitLayer;
+ }
+ }
+
+ return 0;
+}
+
</ins><span class="cx"> void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
</span><span class="cx"> {
</span><span class="cx"> if (m_clipRects) {
</span></span></pre></div>
<a id="trunkWebCorerenderingRenderLayerh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/rendering/RenderLayer.h (59783 => 59784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/rendering/RenderLayer.h 2010-05-19 20:54:53 UTC (rev 59783)
+++ trunk/WebCore/rendering/RenderLayer.h 2010-05-19 21:03:20 UTC (rev 59784)
</span><span class="lines">@@ -303,6 +303,7 @@
</span><span class="cx"> CheckForRepaint = 1 << 1,
</span><span class="cx"> IsCompositingUpdateRoot = 1 << 2,
</span><span class="cx"> UpdateCompositingLayers = 1 << 3,
</span><ins>+ UpdatePagination = 1 << 4
</ins><span class="cx"> };
</span><span class="cx"> typedef unsigned UpdateLayerPositionsFlags;
</span><span class="cx"> void updateLayerPositions(UpdateLayerPositionsFlags = DoFullRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers, IntPoint* cachedOffset = 0);
</span><span class="lines">@@ -478,12 +479,35 @@
</span><span class="cx">
</span><span class="cx"> void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
</span><span class="cx"> PaintBehavior, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0,
</span><del>- PaintLayerFlags paintFlags = 0);
</del><ins>+ PaintLayerFlags = 0);
+ void paintList(Vector<RenderLayer*>*, RenderLayer* rootLayer, GraphicsContext* p,
+ const IntRect& paintDirtyRect, PaintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*,
+ PaintLayerFlags);
+ void paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*,
+ const IntRect& paintDirtyRect, PaintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*,
+ PaintLayerFlags);
+ void paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext*,
+ const IntRect& paintDirtyRect, PaintBehavior,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap*,
+ PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
</ins><span class="cx">
</span><span class="cx"> RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
</span><del>- const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
- const HitTestingTransformState* transformState = 0, double* zOffset = 0);
-
</del><ins>+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
+ const HitTestingTransformState* transformState = 0, double* zOffset = 0);
+ RenderLayer* hitTestList(Vector<RenderLayer*>*, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* transformState, double* zOffsetForDescendants, double* zOffset,
+ const HitTestingTransformState* unflattenedTransformState, bool depthSortDescendants);
+ RenderLayer* hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* transformState, double* zOffset);
+ RenderLayer* hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* transformState, double* zOffset,
+ const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
+
</ins><span class="cx"> PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
</span><span class="cx"> const IntRect& hitTestRect, const IntPoint& hitTestPoint,
</span><span class="cx"> const HitTestingTransformState* containerTransformState) const;
</span><span class="lines">@@ -540,6 +564,9 @@
</span><span class="cx"> void updateScrollCornerStyle();
</span><span class="cx"> void updateResizerStyle();
</span><span class="cx">
</span><ins>+ void updatePagination();
+ bool isPaginated() const { return m_isPaginated; }
+
</ins><span class="cx"> #if USE(ACCELERATED_COMPOSITING)
</span><span class="cx"> bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
</span><span class="cx"> void setHasCompositingDescendant(bool b) { m_hasCompositingDescendant = b; }
</span><span class="lines">@@ -633,6 +660,8 @@
</span><span class="cx"> bool m_visibleDescendantStatusDirty : 1;
</span><span class="cx"> bool m_hasVisibleDescendant : 1;
</span><span class="cx">
</span><ins>+ bool m_isPaginated : 1; // If we think this layer is split by a multi-column ancestor, then this bit will be set.
+
</ins><span class="cx"> bool m_3DTransformedDescendantStatusDirty : 1;
</span><span class="cx"> bool m_has3DTransformedDescendant : 1; // Set on a stacking context layer that has 3D descendants anywhere
</span><span class="cx"> // in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
</span></span></pre>
</div>
</div>
</body>
</html>