Commit cd04e4d6 authored by hyatt's avatar hyatt

Fix two bugs in positionForCoordinates. (Make it work when you have a...

        Fix two bugs in positionForCoordinates.  (Make it work when you have a margin in between your border and
        your first child block.)

        Rewrite column rebalancing to have two modes: constrained and unconstrained.  In unconstrained mode,
        the system will dynamically rebalance as it loses space to breaks and compute a final intrinsic height
        for the overall block.  In constrained mode, columns flow into the fixed height block, and extra columns
        spill out horizontally in the appropriate direction (RTL/LTR).

        Make columns work properly with both LTR and RTL overflow blocks.

        Initial column test suite coming soon now that the basic layout is right.

        Reviewed by darin

        * rendering/RenderBlock.cpp:
        (WebCore:::RenderFlow):
        (WebCore::RenderBlock::layoutBlock):
        (WebCore::RenderBlock::paintColumns):
        (WebCore::RenderBlock::lowestPosition):
        (WebCore::RenderBlock::rightmostPosition):
        (WebCore::RenderBlock::leftmostPosition):
        (WebCore::RenderBlock::hitTestColumns):
        (WebCore::RenderBlock::positionForCoordinates):
        (WebCore::RenderBlock::availableWidth):
        (WebCore::RenderBlock::calcColumnWidth):
        (WebCore::RenderBlock::layoutColumns):
        (WebCore::RenderBlock::adjustPointToColumnContents):
        * rendering/RenderBlock.h:
        (WebCore::RenderBlock::hasColumns):



git-svn-id: svn://svn.chromium.org/blink/trunk@18762 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 9ec8e5b5
2007-01-11 David Hyatt <hyatt@apple.com>
Fix two bugs in positionForCoordinates. (Make it work when you have a margin in between your border and
your first child block.)
Rewrite column rebalancing to have two modes: constrained and unconstrained. In unconstrained mode,
the system will dynamically rebalance as it loses space to breaks and compute a final intrinsic height
for the overall block. In constrained mode, columns flow into the fixed height block, and extra columns
spill out horizontally in the appropriate direction (RTL/LTR).
Make columns work properly with both LTR and RTL overflow blocks.
Initial column test suite coming soon now that the basic layout is right.
Reviewed by darin
* rendering/RenderBlock.cpp:
(WebCore:::RenderFlow):
(WebCore::RenderBlock::layoutBlock):
(WebCore::RenderBlock::paintColumns):
(WebCore::RenderBlock::lowestPosition):
(WebCore::RenderBlock::rightmostPosition):
(WebCore::RenderBlock::leftmostPosition):
(WebCore::RenderBlock::hitTestColumns):
(WebCore::RenderBlock::positionForCoordinates):
(WebCore::RenderBlock::availableWidth):
(WebCore::RenderBlock::calcColumnWidth):
(WebCore::RenderBlock::layoutColumns):
(WebCore::RenderBlock::adjustPointToColumnContents):
* rendering/RenderBlock.h:
(WebCore::RenderBlock::hasColumns):
2007-01-10 Rob Buis <buis@kde.org> 2007-01-10 Rob Buis <buis@kde.org>
Reviewed by Eric. Reviewed by Eric.
......
...@@ -100,8 +100,8 @@ RenderBlock::RenderBlock(Node* node) ...@@ -100,8 +100,8 @@ RenderBlock::RenderBlock(Node* node)
m_overflowHeight = m_overflowWidth = 0; m_overflowHeight = m_overflowWidth = 0;
m_overflowLeft = m_overflowTop = 0; m_overflowLeft = m_overflowTop = 0;
m_tabWidth = -1; m_tabWidth = -1;
m_columnCount = 1; m_desiredColumnCount = 1;
m_columnWidth = 0; m_desiredColumnWidth = 0;
m_columnRects = 0; m_columnRects = 0;
} }
...@@ -461,14 +461,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren) ...@@ -461,14 +461,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
getAbsoluteRepaintRectIncludingFloats(oldBounds, oldFullBounds); getAbsoluteRepaintRectIncludingFloats(oldBounds, oldFullBounds);
int oldWidth = m_width; int oldWidth = m_width;
int oldColumnWidth = m_columnWidth; int oldColumnWidth = m_desiredColumnWidth;
calcWidth(); calcWidth();
calcColumnWidth(); calcColumnWidth();
m_overflowWidth = m_width; m_overflowWidth = m_width;
m_overflowLeft = 0;
if (oldWidth != m_width || oldColumnWidth != m_columnWidth) if (oldWidth != m_width || oldColumnWidth != m_desiredColumnWidth)
relayoutChildren = true; relayoutChildren = true;
clearFloats(); clearFloats();
...@@ -524,12 +525,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren) ...@@ -524,12 +525,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as
// we adjust for clean column breaks. // we adjust for clean column breaks.
layoutColumns(); int singleColumnBottom = layoutColumns();
// Calculate our new height. // Calculate our new height.
int oldHeight = m_height; int oldHeight = m_height;
calcHeight(); calcHeight();
if (oldHeight != m_height) { if (oldHeight != m_height) {
// We have to rebalance columns to the new height.
layoutColumns(singleColumnBottom);
// If the block got expanded in size, then increase our overflowheight to match. // If the block got expanded in size, then increase our overflowheight to match.
if (m_overflowHeight > m_height) if (m_overflowHeight > m_height)
m_overflowHeight -= toAdd; m_overflowHeight -= toAdd;
...@@ -1308,7 +1312,7 @@ void RenderBlock::paintColumns(PaintInfo& paintInfo, int tx, int ty) ...@@ -1308,7 +1312,7 @@ void RenderBlock::paintColumns(PaintInfo& paintInfo, int tx, int ty)
int currXOffset = 0; int currXOffset = 0;
int currYOffset = 0; int currYOffset = 0;
int colGap = columnGap(); int colGap = columnGap();
for (unsigned i = 0; i < m_columnCount; i++) { for (unsigned i = 0; i < m_columnRects->size(); i++) {
// For each rect, we clip to the rect, and then we adjust our coords. // For each rect, we clip to the rect, and then we adjust our coords.
IntRect colRect = m_columnRects->at(i); IntRect colRect = m_columnRects->at(i);
colRect.move(tx, ty); colRect.move(tx, ty);
...@@ -2198,27 +2202,15 @@ IntRect RenderBlock::floatRect() const ...@@ -2198,27 +2202,15 @@ IntRect RenderBlock::floatRect() const
return result; return result;
} }
int int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{ {
int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf); int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip()) if (!includeOverflowInterior && hasOverflowClip())
return bottom; return bottom;
if (m_overflowHeight > m_height) if (includeSelf && m_overflowHeight > bottom)
bottom = max(m_overflowHeight, bottom); bottom = m_overflowHeight;
if (m_floatingObjects && !hasColumns()) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
bottom = max(bottom, lp);
}
}
}
if (m_positionedObjects) { if (m_positionedObjects) {
RenderObject* r; RenderObject* r;
DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects); DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
...@@ -2232,7 +2224,25 @@ RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) cons ...@@ -2232,7 +2224,25 @@ RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) cons
} }
} }
if (!includeSelf && lastLineBox() && !hasColumns()) { if (hasColumns()) {
for (unsigned i = 0; i < m_columnRects->size(); i++)
bottom = max(bottom, m_columnRects->at(i).bottom());
return bottom;
}
if (m_floatingObjects) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
bottom = max(bottom, lp);
}
}
}
if (!includeSelf && lastLineBox()) {
int lp = lastLineBox()->yPos() + lastLineBox()->height(); int lp = lastLineBox()->yPos() + lastLineBox()->height();
bottom = max(bottom, lp); bottom = max(bottom, lp);
} }
...@@ -2245,19 +2255,9 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel ...@@ -2245,19 +2255,9 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf); int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip()) if (!includeOverflowInterior && hasOverflowClip())
return right; return right;
if (includeSelf && m_overflowWidth > right) if (includeSelf && m_overflowWidth > right)
right = m_overflowWidth; right = m_overflowWidth;
if (m_floatingObjects && !hasColumns()) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
right = max(right, rp);
}
}
}
if (m_positionedObjects) { if (m_positionedObjects) {
RenderObject* r; RenderObject* r;
...@@ -2272,7 +2272,25 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel ...@@ -2272,7 +2272,25 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
} }
} }
if (!includeSelf && firstLineBox() && !hasColumns()) { if (hasColumns()) {
// This only matters for LTR
if (style()->direction() == LTR)
right = max(m_columnRects->last().right(), right);
return right;
}
if (m_floatingObjects) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
right = max(right, rp);
}
}
}
if (!includeSelf && firstLineBox()) {
for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) { for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
int rp = currBox->xPos() + currBox->width(); int rp = currBox->xPos() + currBox->width();
// If this node is a root editable element, then the rightmostPosition should account for a caret at the end. // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
...@@ -2291,20 +2309,10 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf ...@@ -2291,20 +2309,10 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf); int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip()) if (!includeOverflowInterior && hasOverflowClip())
return left; return left;
if (includeSelf && m_overflowLeft < left) if (includeSelf && m_overflowLeft < left)
left = m_overflowLeft; left = m_overflowLeft;
if (m_floatingObjects && !hasColumns()) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
left = min(left, lp);
}
}
}
if (m_positionedObjects) { if (m_positionedObjects) {
RenderObject* r; RenderObject* r;
DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects); DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
...@@ -2317,8 +2325,26 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf ...@@ -2317,8 +2325,26 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
} }
} }
} }
if (!includeSelf && firstLineBox() && !hasColumns()) { if (hasColumns()) {
// This only matters for RTL
if (style()->direction() == RTL)
left = min(m_columnRects->last().x(), left);
return left;
}
if (m_floatingObjects) {
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (!r->noPaint || r->node->layer()) {
int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
left = min(left, lp);
}
}
}
if (!includeSelf && firstLineBox()) {
for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
left = min(left, (int)currBox->xPos()); left = min(left, (int)currBox->xPos());
} }
...@@ -2689,7 +2715,7 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r ...@@ -2689,7 +2715,7 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r
int currXOffset = 0; int currXOffset = 0;
int currYOffset = 0; int currYOffset = 0;
int colGap = columnGap(); int colGap = columnGap();
for (unsigned i = 0; i < m_columnCount; i++) { for (unsigned i = 0; i < m_columnRects->size(); i++) {
IntRect colRect = m_columnRects->at(i); IntRect colRect = m_columnRects->at(i);
colRect.move(tx, ty); colRect.move(tx, ty);
...@@ -2800,7 +2826,7 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y) ...@@ -2800,7 +2826,7 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
} }
// If we start inside the shadow tree, we will stay inside (even if the point is above or below). // If we start inside the shadow tree, we will stay inside (even if the point is above or below).
if (!(n && n->isShadowNode())) { if (!(n && n->isShadowNode()) && !childrenInline()) {
// Don't return positions inside editable roots for coordinates outside those roots, except for coordinates outside // Don't return positions inside editable roots for coordinates outside those roots, except for coordinates outside
// a document that is entirely editable. // a document that is entirely editable.
bool isEditableRoot = n && n->rootEditableElement() == n && !n->hasTagName(bodyTag) && !n->hasTagName(htmlTag); bool isEditableRoot = n && n->rootEditableElement() == n && !n->hasTagName(bodyTag) && !n->hasTagName(htmlTag);
...@@ -2871,6 +2897,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y) ...@@ -2871,6 +2897,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
} }
// See if any child blocks exist at this y coordinate. // See if any child blocks exist at this y coordinate.
if (firstChild() && contentsY < firstChild()->yPos())
return VisiblePosition(n, 0, DOWNSTREAM);
for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) { for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned()) if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned())
continue; continue;
...@@ -2891,8 +2919,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y) ...@@ -2891,8 +2919,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
int RenderBlock::availableWidth() const int RenderBlock::availableWidth() const
{ {
// If we have multiple columns, then the available width is reduced to our column width. // If we have multiple columns, then the available width is reduced to our column width.
if (m_columnCount > 1) if (hasColumns())
return m_columnWidth; return m_desiredColumnWidth;
return contentWidth(); return contentWidth();
} }
...@@ -2906,30 +2934,30 @@ int RenderBlock::columnGap() const ...@@ -2906,30 +2934,30 @@ int RenderBlock::columnGap() const
void RenderBlock::calcColumnWidth() void RenderBlock::calcColumnWidth()
{ {
// Calculate our column width and column count. // Calculate our column width and column count.
m_columnCount = 1; m_desiredColumnCount = 1;
m_columnWidth = contentWidth(); m_desiredColumnWidth = contentWidth();
// For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination. // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
if (document()->printing() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) if (document()->printing() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth()))
return; return;
int availWidth = m_columnWidth; int availWidth = m_desiredColumnWidth;
int colGap = columnGap(); int colGap = columnGap();
if (style()->hasAutoColumnWidth()) { if (style()->hasAutoColumnWidth()) {
int colCount = style()->columnCount(); int colCount = style()->columnCount();
if ((colCount - 1) * colGap < availWidth) { if ((colCount - 1) * colGap < availWidth) {
m_columnCount = colCount; m_desiredColumnCount = colCount;
m_columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount; m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount;
} else if (colGap < availWidth) { } else if (colGap < availWidth) {
m_columnCount = availWidth / colGap; m_desiredColumnCount = availWidth / colGap;
m_columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount; m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount;
} }
} else if (style()->hasAutoColumnCount()) { } else if (style()->hasAutoColumnCount()) {
int colWidth = static_cast<int>(style()->columnWidth()); int colWidth = static_cast<int>(style()->columnWidth());
if (colWidth < availWidth) { if (colWidth < availWidth) {
m_columnCount = (availWidth + colGap) / (colWidth + colGap); m_desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
m_columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount; m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount;
} }
} else { } else {
// Both are set. // Both are set.
...@@ -2937,24 +2965,33 @@ void RenderBlock::calcColumnWidth() ...@@ -2937,24 +2965,33 @@ void RenderBlock::calcColumnWidth()
int colCount = style()->columnCount(); int colCount = style()->columnCount();
if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) { if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) {
m_columnCount = colCount; m_desiredColumnCount = colCount;
m_columnWidth = colWidth; m_desiredColumnWidth = colWidth;
} else if (colWidth < availWidth) { } else if (colWidth < availWidth) {
m_columnCount = (availWidth + colGap) / (colWidth + colGap); m_desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
m_columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount; m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount;
} }
} }
} }
void RenderBlock::layoutColumns() int RenderBlock::layoutColumns(int endOfContent)
{ {
// Don't do anything if we have no columns // Don't do anything if we have no columns
if (!hasColumns()) if (!hasColumns())
return; return -1;
bool computeIntrinsicHeight = (endOfContent == -1);
// Fill the columns in to the available height. Attempt to balance the height of the columns // Fill the columns in to the available height. Attempt to balance the height of the columns
int availableHeight = contentHeight(); int availableHeight = contentHeight();
int colHeight = availableHeight / m_columnCount + lineHeight(false) / 2; // Add in half our line-height to help with best-guess initial balancing. int colHeight = computeIntrinsicHeight ? availableHeight / m_desiredColumnCount : availableHeight;
// Add in half our line-height to help with best-guess initial balancing.
int columnSlop = lineHeight(false) / 2;
int remainingSlopSpace = columnSlop * m_desiredColumnCount;
if (computeIntrinsicHeight)
colHeight += columnSlop;
int colGap = columnGap(); int colGap = columnGap();
...@@ -2968,27 +3005,30 @@ void RenderBlock::layoutColumns() ...@@ -2968,27 +3005,30 @@ void RenderBlock::layoutColumns()
RenderView* v = view(); RenderView* v = view();
int left = borderLeft() + paddingLeft(); int left = borderLeft() + paddingLeft();
int top = borderTop() + paddingTop(); int top = borderTop() + paddingTop();
int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - m_columnWidth; int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - m_desiredColumnWidth;
int currY = top; int currY = top;
int colCount = m_columnCount; unsigned colCount = m_desiredColumnCount;
int maxColBottom = borderTop() + paddingTop(); int maxColBottom = borderTop() + paddingTop();
for (unsigned i = 0; i < m_columnCount; i++) { int contentBottom = top + availableHeight;
// The last column just gets all the remaining space. for (unsigned i = 0; i < colCount; i++) {
if (i == m_columnCount - 1) // If we aren't constrained, then the last column can just get all the remaining space.
if (computeIntrinsicHeight && i == colCount - 1)
colHeight = availableHeight; colHeight = availableHeight;
// This represents the real column position. // This represents the real column position.
IntRect colRect(currX, top, m_columnWidth, colHeight); IntRect colRect(currX, top, m_desiredColumnWidth, colHeight);
// For the simulated paint, we pretend like everything is in one long strip. // For the simulated paint, we pretend like everything is in one long strip.
IntRect pageRect(left, currY, m_columnWidth, colHeight); IntRect pageRect(left, currY, m_desiredColumnWidth, colHeight);
v->setPrintRect(pageRect); v->setPrintRect(pageRect);
v->setTruncatedAt(currY + colHeight); v->setTruncatedAt(currY + colHeight);
GraphicsContext context((PlatformGraphicsContext*)0); GraphicsContext context((PlatformGraphicsContext*)0);
RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0); RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0);
m_columnCount = 1;
int oldColCount = m_desiredColumnCount;
m_desiredColumnCount = 1;
paintObject(paintInfo, 0, 0); paintObject(paintInfo, 0, 0);
m_columnCount = colCount; m_desiredColumnCount = oldColCount;
int adjustedBottom = v->bestTruncatedAt(); int adjustedBottom = v->bestTruncatedAt();
if (adjustedBottom <= currY) if (adjustedBottom <= currY)
...@@ -2996,10 +3036,23 @@ void RenderBlock::layoutColumns() ...@@ -2996,10 +3036,23 @@ void RenderBlock::layoutColumns()
colRect.setHeight(adjustedBottom - currY); colRect.setHeight(adjustedBottom - currY);
// Add in the lost space to the subsequent columns.
// FIXME: This will create a "staircase" effect if there are enough columns, but the effect should be pretty subtle.
if (computeIntrinsicHeight) {
int lostSpace = colHeight - colRect.height();
if (lostSpace > remainingSlopSpace) {
// Redestribute the space among the remaining columns.
int spaceToRedistribute = lostSpace - remainingSlopSpace;
int remainingColumns = colCount - i + 1;
colHeight += spaceToRedistribute / remainingColumns;
}
remainingSlopSpace = max(0, remainingSlopSpace - lostSpace);
}
if (style()->direction() == LTR) if (style()->direction() == LTR)
currX += m_columnWidth + colGap; currX += m_desiredColumnWidth + colGap;
else else
currX -= (m_columnWidth + colGap); currX -= (m_desiredColumnWidth + colGap);
currY += colRect.height(); currY += colRect.height();
availableHeight -= colRect.height(); availableHeight -= colRect.height();
...@@ -3007,19 +3060,29 @@ void RenderBlock::layoutColumns() ...@@ -3007,19 +3060,29 @@ void RenderBlock::layoutColumns()
maxColBottom = max(colRect.bottom(), maxColBottom); maxColBottom = max(colRect.bottom(), maxColBottom);
m_columnRects->append(colRect); m_columnRects->append(colRect);
// Start adding in more columns as long as there's still content left.
if (currY < endOfContent && i == colCount - 1)
colCount++;
} }
m_overflowWidth = max(m_width, currX - colGap);
m_overflowLeft = min(0, currX + m_desiredColumnWidth + colGap);
m_overflowHeight = maxColBottom; m_overflowHeight = maxColBottom;
int toAdd = borderBottom() + paddingBottom(); int toAdd = borderBottom() + paddingBottom();
if (includeHorizontalScrollbarSize()) if (includeHorizontalScrollbarSize())
toAdd += m_layer->horizontalScrollbarHeight(); toAdd += m_layer->horizontalScrollbarHeight();
m_height = m_overflowHeight + toAdd;
m_overflowWidth = m_width; if (computeIntrinsicHeight)
m_height = m_overflowHeight + toAdd;
v->setPrintRect(IntRect()); v->setPrintRect(IntRect());
v->setTruncatedAt(0); v->setTruncatedAt(0);
ASSERT(m_columnRects && m_columnCount == m_columnRects->size()); ASSERT(m_columnRects && colCount == m_columnRects->size());
return contentBottom;
} }
void RenderBlock::adjustPointToColumnContents(IntPoint& point) const void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
...@@ -3032,17 +3095,20 @@ void RenderBlock::adjustPointToColumnContents(IntPoint& point) const ...@@ -3032,17 +3095,20 @@ void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
int colGap = columnGap(); int colGap = columnGap();
int leftGap = colGap / 2; int leftGap = colGap / 2;
IntPoint columnPoint(m_columnRects->at(0).location()); IntPoint columnPoint(m_columnRects->at(0).location());
int yOffset = 0;
for (unsigned i = 0; i < m_columnRects->size(); i++) { for (unsigned i = 0; i < m_columnRects->size(); i++) {
// Add in half the column gap to the left and right of the rect. // Add in half the column gap to the left and right of the rect.
IntRect colRect = m_columnRects->at(i); IntRect colRect = m_columnRects->at(i);
IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height()); IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height());
if (gapAndColumnRect.contains(point)) if (gapAndColumnRect.contains(point)) {
// We're inside the column. Translate the x and y into our column coordinate space. // We're inside the column. Translate the x and y into our column coordinate space.
point -= columnPoint - colRect.location(); point.move(columnPoint.x() - colRect.x(), yOffset);
return;
}
// Move to the next position. // Move to the next position.
columnPoint.setY(columnPoint.y() + colRect.height()); yOffset += colRect.height();
} }
} }
......
...@@ -280,7 +280,7 @@ public: ...@@ -280,7 +280,7 @@ public:
int heightForLineCount(int); int heightForLineCount(int);
void clearTruncation(); void clearTruncation();
virtual bool hasColumns() const { return m_columnCount > 1; } virtual bool hasColumns() const { return m_desiredColumnCount > 1; }
void adjustRectForColumns(IntRect&) const; void adjustRectForColumns(IntRect&) const;
private: private:
void adjustPointToColumnContents(IntPoint&) const; void adjustPointToColumnContents(IntPoint&) const;
...@@ -295,7 +295,7 @@ private: ...@@ -295,7 +295,7 @@ private:
int columnGap() const; int columnGap() const;
void calcColumnWidth(); void calcColumnWidth();
void layoutColumns(); int layoutColumns(int endOfContent = -1);
protected: protected:
struct FloatingObject { struct FloatingObject {
...@@ -461,8 +461,8 @@ private: ...@@ -461,8 +461,8 @@ private:
int m_tabWidth; int m_tabWidth;
// Column information. // Column information.
int m_columnWidth; int m_desiredColumnWidth;
unsigned m_columnCount; unsigned m_desiredColumnCount;
Vector<IntRect>* m_columnRects; Vector<IntRect>* m_columnRects;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment