summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering/RenderBlock.cpp')
-rw-r--r--WebCore/rendering/RenderBlock.cpp182
1 files changed, 101 insertions, 81 deletions
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index 62e177d..3f53456 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -187,7 +187,7 @@ void RenderBlock::destroy()
// that will outlast this block. In the non-anonymous block case those
// children will be destroyed by the time we return from this function.
if (isAnonymousBlock()) {
- for (InlineFlowBox* box = firstLineBox(); box; box = box->nextFlowBox()) {
+ for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) {
while (InlineBox* childBox = box->firstChild())
childBox->remove();
}
@@ -265,8 +265,14 @@ void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
- if (!beforeChild && isAfterContent(lastChild()))
- beforeChild = lastChild();
+ if (!beforeChild) {
+ RenderObject* lastRenderer = lastChild();
+
+ if (isAfterContent(lastRenderer))
+ beforeChild = lastRenderer;
+ else if (lastRenderer && lastRenderer->isAnonymousBlock() && isAfterContent(lastRenderer->lastChild()))
+ beforeChild = lastRenderer->lastChild();
+ }
bool madeBoxesNonInline = false;
@@ -786,8 +792,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
if (previousHeight != height())
relayoutChildren = true;
- // It's weird that we're treating float information as normal flow overflow, but we do this because floatRect() isn't
- // able to be propagated up the render tree yet. Overflow information is however. This check is designed to catch anyone
+ // This check is designed to catch anyone
// who wasn't going to propagate float information up to the parent and yet could potentially be painted by its ancestor.
if (isRoot() || expandsToEncloseOverhangingFloats())
addOverflowFromFloats();
@@ -827,11 +832,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
if (hasOverflowClip()) {
// Adjust repaint rect for scroll offset
- int x = repaintRect.x();
- int y = repaintRect.y();
- layer()->subtractScrolledContentOffset(x, y);
- repaintRect.setX(x);
- repaintRect.setY(y);
+ repaintRect.move(-layer()->scrolledContentOffset());
// Don't allow this rect to spill out of our overflow box.
repaintRect.intersect(IntRect(0, 0, width(), height()));
@@ -1568,7 +1569,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
{
- const Color& ruleColor = style()->columnRuleColor();
+ const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
bool ruleTransparent = style()->columnRuleIsTransparent();
EBorderStyle ruleStyle = style()->columnRuleStyle();
int ruleWidth = style()->columnRuleWidth();
@@ -1603,7 +1604,7 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
int ruleTop = ty + borderTop() + paddingTop();
int ruleBottom = ruleTop + contentHeight();
drawLineForBoxSide(paintInfo.context, ruleStart, ruleTop, ruleEnd, ruleBottom,
- style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0);
+ style()->direction() == LTR ? BSLeft : BSRight, ruleColor, ruleStyle, 0, 0);
}
ruleX = currXOffset;
@@ -1680,16 +1681,15 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// Check for page-break-before: always, and if it's set, break and bail.
- if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
- inRootBlockContext() && (ty + child->y()) > paintInfo.rect.y() &&
- (ty + child->y()) < paintInfo.rect.bottom()) {
+ if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS
+ && (ty + child->y()) > paintInfo.rect.y()
+ && (ty + child->y()) < paintInfo.rect.bottom()) {
view()->setBestTruncatedAt(ty + child->y(), this, true);
return;
}
// Check for page-break-inside: avoid, and it it's set, break and bail.
if (isPrinting && !childrenInline() && child->style()->pageBreakInside() == PBAVOID
- && inRootBlockContext()
&& ty + child->y() > paintInfo.rect.y()
&& ty + child->y() < paintInfo.rect.bottom()
&& ty + child->y() + child->height() > paintInfo.rect.bottom()) {
@@ -1701,9 +1701,9 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
child->paint(info, tx, ty);
// Check for page-break-after: always, and if it's set, break and bail.
- if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS &&
- inRootBlockContext() && (ty + child->y() + child->height()) > paintInfo.rect.y() &&
- (ty + child->y() + child->height()) < paintInfo.rect.bottom()) {
+ if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS
+ && (ty + child->y() + child->height()) > paintInfo.rect.y()
+ && (ty + child->y() + child->height()) < paintInfo.rect.bottom()) {
view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginBottom()), this, true);
return;
}
@@ -1750,11 +1750,14 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
if (paintPhase == PaintPhaseBlockBackground)
return;
- // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
+ // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
int scrolledX = tx;
int scrolledY = ty;
- if (hasOverflowClip())
- layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
+ if (hasOverflowClip()) {
+ IntSize offset = layer()->scrolledContentOffset();
+ scrolledX -= offset.width();
+ scrolledY -= offset.height();
+ }
// 2. paint contents
if (paintPhase != PaintPhaseSelfOutline) {
@@ -1780,7 +1783,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
// 5. paint outline.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
- paintOutline(paintInfo.context, tx, ty, width(), height(), style());
+ paintOutline(paintInfo.context, tx, ty, width(), height());
// 6. paint continuation outlines.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
@@ -1966,18 +1969,16 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC
// FIXME: this is broken with transforms
TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
mapLocalToContainer(repaintContainer, false, false, transformState);
- FloatPoint offsetFromRepaintContainer = transformState.mappedPoint();
- int x = offsetFromRepaintContainer.x();
- int y = offsetFromRepaintContainer.y();
+ IntPoint offsetFromRepaintContainer = roundedIntPoint(transformState.mappedPoint());
if (hasOverflowClip())
- layer()->subtractScrolledContentOffset(x, y);
+ offsetFromRepaintContainer -= layer()->scrolledContentOffset();
int lastTop = 0;
int lastLeft = leftSelectionOffset(this, lastTop);
int lastRight = rightSelectionOffset(this, lastTop);
- return fillSelectionGaps(this, x, y, x, y, lastTop, lastLeft, lastRight);
+ return fillSelectionGaps(this, offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), lastTop, lastLeft, lastRight);
}
void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
@@ -2380,8 +2381,14 @@ void RenderBlock::removeFloatingObject(RenderBox* o)
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
while (it.current()) {
if (it.current()->m_renderer == o) {
- if (childrenInline())
- markLinesDirtyInVerticalRange(0, it.current()->m_bottom);
+ if (childrenInline()) {
+ int bottom = it.current()->m_bottom;
+ // Special-case zero- and less-than-zero-height floats: those don't touch
+ // the line that they're on, but it still needs to be dirtied. This is
+ // accomplished by pretending they have a height of 1.
+ bottom = max(bottom, it.current()->m_top + 1);
+ markLinesDirtyInVerticalRange(0, bottom);
+ }
m_floatingObjects->removeRef(it.current());
}
++it;
@@ -2660,24 +2667,6 @@ RenderBlock::floatBottom() const
return bottom;
}
-IntRect RenderBlock::floatRect() const
-{
- IntRect result;
- if (!m_floatingObjects || hasOverflowClip() || hasColumns())
- return result;
- FloatingObject* r;
- DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for (; (r = it.current()); ++it) {
- if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
- IntRect childRect = r->m_renderer->visibleOverflowRect();
- childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
- result.unite(childRect);
- }
- }
-
- return result;
-}
-
int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
int bottom = includeSelf && width() > 0 ? height() : 0;
@@ -2846,7 +2835,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
if (!includeSelf) {
right = max(right, borderLeft() + paddingLeft() + paddingRight() + relativeOffset);
if (childrenInline()) {
- for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
+ for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
int childRightEdge = currBox->x() + currBox->width();
// If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
@@ -2941,7 +2930,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
}
if (!includeSelf && firstLineBox()) {
- for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
+ for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
left = min(left, (int)currBox->x() + relativeOffset);
}
@@ -3050,8 +3039,8 @@ void RenderBlock::clearFloats()
addIntrudingFloats(block, xoffset, offset);
if (childrenInline()) {
- int changeTop = INT_MAX;
- int changeBottom = INT_MIN;
+ int changeTop = numeric_limits<int>::max();
+ int changeBottom = numeric_limits<int>::min();
if (m_floatingObjects) {
for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
@@ -3228,6 +3217,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.
@@ -3319,8 +3334,11 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test descendants first.
int scrolledX = tx;
int scrolledY = ty;
- if (hasOverflowClip())
- layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
+ if (hasOverflowClip()) {
+ IntSize offset = layer()->scrolledContentOffset();
+ scrolledX -= offset.width();
+ scrolledY -= offset.height();
+ }
// Hit test contents if we don't have columns.
if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
@@ -3595,15 +3613,16 @@ VisiblePosition RenderBlock::positionForPoint(const IntPoint& point)
void RenderBlock::offsetForContents(int& tx, int& ty) const
{
+ IntPoint contentsPoint(tx, ty);
+
if (hasOverflowClip())
- layer()->addScrolledContentOffset(tx, ty);
+ contentsPoint += layer()->scrolledContentOffset();
- if (hasColumns()) {
- IntPoint contentsPoint(tx, ty);
+ if (hasColumns())
adjustPointToColumnContents(contentsPoint);
- tx = contentsPoint.x();
- ty = contentsPoint.y();
- }
+
+ tx = contentsPoint.x();
+ ty = contentsPoint.y();
}
int RenderBlock::availableWidth() const
@@ -3765,11 +3784,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);
@@ -3784,7 +3805,7 @@ int RenderBlock::layoutColumns(int endOfContent, int requestedColumnHeight)
int adjustedBottom = v->bestTruncatedAt();
if (adjustedBottom <= currY)
- adjustedBottom = currY + colHeight;
+ adjustedBottom = truncationPoint;
colRect.setHeight(adjustedBottom - currY);
@@ -3859,8 +3880,20 @@ void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
// Add in half the column gap to the left and right of the rect.
IntRect colRect = colRects->at(i);
IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height());
-
- if (gapAndColumnRect.contains(point)) {
+
+ if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRect.right()) {
+ // FIXME: The clamping that follows is not completely right for right-to-left
+ // content.
+ // Clamp everything above the column to its top left.
+ if (point.y() < gapAndColumnRect.y())
+ point = gapAndColumnRect.location();
+ // Clamp everything below the column to the next column's top left. If there is
+ // no next column, this still maps to just after this column.
+ else if (point.y() >= gapAndColumnRect.bottom()) {
+ point = gapAndColumnRect.location();
+ point.move(0, gapAndColumnRect.height());
+ }
+
// We're inside the column. Translate the x and y into our column coordinate space.
point.move(columnPoint.x() - colRect.x(), yOffset);
return;
@@ -4635,7 +4668,7 @@ void RenderBlock::updateFirstLetter()
// Drill into inlines looking for our first text child.
RenderObject* currChild = firstLetterBlock->firstChild();
- while (currChild && currChild->needsLayout() && (!currChild->isReplaced() || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
+ while (currChild && currChild->needsLayout() && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
if (currChild->isFloatingOrPositioned()) {
if (currChild->style()->styleType() == FIRST_LETTER)
break;
@@ -4722,9 +4755,7 @@ void RenderBlock::updateFirstLetter()
// construct text fragment for the first letter
RenderTextFragment* letter =
new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(pseudoStyle);
- letter->setStyle(newStyle.release());
+ letter->setStyle(pseudoStyle);
firstLetter->addChild(letter);
textObj->destroy();
@@ -4733,17 +4764,6 @@ void RenderBlock::updateFirstLetter()
}
}
-bool RenderBlock::inRootBlockContext() const
-{
- if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
- return false;
-
- if (isRoot() || isRenderView())
- return true;
-
- return containingBlock()->inRootBlockContext();
-}
-
// Helper methods for obtaining the last line, computing line counts and heights for line counts
// (crawling into blocks).
static bool shouldCheckLines(RenderObject* obj)