Skip to content
Permalink
Browse files
<rdar://problem/7722008> Column breaking ignores floats
https://bugs.webkit.org/show_bug.cgi?id=35837

Reviewed by Simon Fraser.

WebCore:

Test: fast/multicol/float-truncation.html

Introduce an earlier column-break if otherwise a float that could fit
inside a single column will be split between columns.

It is still possible for floats to be needlessly broken if initially
they fit in the column, but normal flow truncation then shortens the
column.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::visibleTopOfHighestFloatExtendingBelow): Added.
Returns the visible top of the highest descendant float that visibly
extends below the given y offset, ignoring floats that are taller than
the given maximum height.
(WebCore::RenderBlock::layoutColumns): If the initial column height
would cause a float to be split, truncate above the float.
* rendering/RenderBlock.h:

LayoutTests:

* fast/multicol/float-truncation-expected.txt: Added.
* fast/multicol/float-truncation.html: Added.



Canonical link: https://commits.webkit.org/46933@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@55636 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Dan Bernstein committed Mar 7, 2010
1 parent 3c4d210 commit 49bab0bd0ae31cb279849661e1d675017e2b47dc
Showing 6 changed files with 170 additions and 4 deletions.
@@ -1,3 +1,13 @@
2010-03-07 Dan Bernstein <mitz@apple.com>

Reviewed by Simon Fraser.

<rdar://problem/7722008> Column breaking ignores floats
https://bugs.webkit.org/show_bug.cgi?id=35837

* fast/multicol/float-truncation-expected.txt: Added.
* fast/multicol/float-truncation.html: Added.

2010-03-07 Dmitry Titov <dimich@chromium.org>

Not reviewed. Revert of r55593 which caused a regression of worker-cloneports.html.
@@ -0,0 +1 @@
PASS
@@ -0,0 +1,101 @@
<style>
div.columns {
width: 200px;
-webkit-columns: 2;
-webkit-column-gap: 0;
outline: 1px solid blue;
font-family: ahem;
font-size: 10px;
margin: 5px;
overflow: hidden;
}

div.float {
float: left;
width: 50px;
margin-top: 5px;
color: silver;
}
</style>
<div id="tests">
<div class="columns" style="height: 80px;">
one line two lines three lines
<div class="float" id="f1">
three line float
</div>
text runs here next to the float
</div>
<!-- In this case, the float fits, but then the main content causes the break
to occur earlier and the float gets split. -->
<div class="columns" style="height: 75px;">
one line two lines three lines
<div class="float" id="f2">
three line float
</div>
text runs here next to the float
</div>
<!-- In this case, the float forces an early column break. -->
<div class="columns" style="height: 70px;">
one line two lines three lines
<div class="float" id="f3">
three line float
</div>
text runs here next to the float
</div>
<!-- In this case, the float forces an early column break. -->
<div class="columns" style="height: 70px;">
one line two lines three lines and some more
<div class="float" id="f4">
three line float
</div>
text runs here next to the float
</div>
<!-- In this case, the float is too tall to fit anyway, so it doesn't
affect column breaks. -->
<div class="columns" style="height: 45px;">
one line
<div class="float" id="f5">
and one five line float
</div>
text runs here next to the float
</div>
</div>
<pre id="result"></pre>
<script>
function floatOffset(float)
{
var range = document.createRange();
range.setStart(float, 0);
range.setEnd(float, 0);
range.expand("word");
var rect = range.getBoundingClientRect();
var parentRect = float.parentNode.getBoundingClientRect();
return { width: rect.left - parentRect.left, height: rect.top - parentRect.top };
}

var tests = [
["f1", 0, 45],
["f2", 0, 45],
["f3", 100, 5],
["f4", 100, 5],
["f5", 0, 15]
];

var test;
var failures = 0;
while (test = tests.shift()) {
var float = document.getElementById(test[0]);
var result = floatOffset(float);
var passed = result.width === test[1] && result.height === test[2]
float.style.color = passed ? "green" : "red";
if (!passed)
failures++
}

if (window.layoutTestController) {
layoutTestController.dumpAsText();
document.getElementById("tests").style.display = "none";
}

document.getElementById("result").innerText = failures ? "FAIL: " + failures + " cases failed" : "PASS";
</script>
@@ -1,3 +1,28 @@
2010-03-07 Dan Bernstein <mitz@apple.com>

Reviewed by Simon Fraser.

<rdar://problem/7722008> Column breaking ignores floats
https://bugs.webkit.org/show_bug.cgi?id=35837

Test: fast/multicol/float-truncation.html

Introduce an earlier column-break if otherwise a float that could fit
inside a single column will be split between columns.

It is still possible for floats to be needlessly broken if initially
they fit in the column, but normal flow truncation then shortens the
column.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::visibleTopOfHighestFloatExtendingBelow): Added.
Returns the visible top of the highest descendant float that visibly
extends below the given y offset, ignoring floats that are taller than
the given maximum height.
(WebCore::RenderBlock::layoutColumns): If the initial column height
would cause a float to be split, truncate above the float.
* rendering/RenderBlock.h:

2010-03-07 Dmitry Titov <dimich@chromium.org>

Not reviewed. Revert of r55593 which caused a regression of worker-cloneports.html.
@@ -3182,6 +3182,32 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove
}
}

int RenderBlock::visibleTopOfHighestFloatExtendingBelow(int bottom, int maxHeight) const
{
int top = bottom;
if (m_floatingObjects) {
FloatingObject* floatingObject;
for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); (floatingObject = it.current()); ++it) {
RenderBox* floatingBox = floatingObject->m_renderer;
IntRect visibleOverflow = floatingBox->visibleOverflowRect();
visibleOverflow.move(floatingBox->x(), floatingBox->y());
if (visibleOverflow.y() < top && visibleOverflow.bottom() > bottom && visibleOverflow.height() <= maxHeight && floatingBox->containingBlock() == this)
top = visibleOverflow.y();
}
}

if (!childrenInline()) {
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isFloatingOrPositioned() || !child->isRenderBlock())
continue;
RenderBlock* childBlock = toRenderBlock(child);
top = min(top, childBlock->y() + childBlock->visibleTopOfHighestFloatExtendingBelow(bottom - childBlock->y(), maxHeight));
}
}

return top;
}

int RenderBlock::getClearDelta(RenderBox* child, int yPos)
{
// There is no need to compute clearance if we have no floats.
@@ -3723,11 +3749,13 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight)

// This represents the real column position.
IntRect colRect(currX, top, desiredColumnWidth, colHeight);


int truncationPoint = visibleTopOfHighestFloatExtendingBelow(currY + colHeight, colHeight);

// For the simulated paint, we pretend like everything is in one long strip.
IntRect pageRect(left, currY, desiredColumnWidth, colHeight);
IntRect pageRect(left, currY, desiredColumnWidth, truncationPoint - currY);
v->setPrintRect(pageRect);
v->setTruncatedAt(currY + colHeight);
v->setTruncatedAt(truncationPoint);
GraphicsContext context((PlatformGraphicsContext*)0);
RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0);

@@ -3742,7 +3770,7 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight)

int adjustedBottom = v->bestTruncatedAt();
if (adjustedBottom <= currY)
adjustedBottom = currY + colHeight;
adjustedBottom = truncationPoint;

colRect.setHeight(adjustedBottom - currY);

@@ -371,6 +371,7 @@ class RenderBlock : public RenderBox {

void calcColumnWidth();
int layoutColumns(int endOfContent = -1, int requestedColumnHeight = -1);
int visibleTopOfHighestFloatExtendingBelow(int bottom, int maxHeight) const;

bool expandsToEncloseOverhangingFloats() const;

0 comments on commit 49bab0b

Please sign in to comment.