summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderBlock.cpp')
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp349
1 files changed, 237 insertions, 112 deletions
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 9b2bca5a9..413c60ece 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -114,8 +114,8 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderP
m_quirkContainer = block->isTableCell() || block->isBody() || blockStyle->marginBeforeCollapse() == MDISCARD
|| blockStyle->marginAfterCollapse() == MDISCARD;
- m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0;
- m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0;
+ m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : zeroLayoutUnit;
+ m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : zeroLayoutUnit;
}
// -------------------------------------------------------------------------------------------------------
@@ -429,14 +429,24 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render
RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
{
+ RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
for (RenderObject* curr = this; curr; curr = curr->parent()) {
if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
|| curr->isInlineBlockOrInlineTable())
return 0;
+
+ // FIXME: Table manages its own table parts, most of which are RenderBoxes.
+ // Multi-column code cannot handle splitting the flow in table. Disabling it
+ // to prevent crashes.
+ if (curr->isTable())
+ return 0;
RenderBlock* currBlock = toRenderBlock(curr);
+ if (!currBlock->createsAnonymousWrapper())
+ firstChildIgnoringAnonymousWrappers = currBlock;
+
if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
- return currBlock;
+ return firstChildIgnoringAnonymousWrappers;
if (currBlock->isAnonymousColumnSpanBlock())
return 0;
@@ -447,15 +457,20 @@ RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
RenderBlock* RenderBlock::clone() const
{
RenderBlock* cloneBlock;
- if (isAnonymousBlock())
+ if (isAnonymousBlock()) {
cloneBlock = createAnonymousBlock();
+ cloneBlock->setChildrenInline(childrenInline());
+ }
else {
- cloneBlock = new (renderArena()) RenderBlock(node());
+ RenderObject* cloneRenderer = node()->createRenderer(renderArena(), style());
+ cloneBlock = toRenderBlock(cloneRenderer);
cloneBlock->setStyle(style());
- if (!childrenInline() && cloneBlock->firstChild() && cloneBlock->firstChild()->isInline())
- cloneBlock->makeChildrenNonInline();
+
+ // This takes care of setting the right value of childrenInline in case
+ // generated content is added to cloneBlock and 'this' does not have
+ // generated content added yet.
+ cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());
}
- cloneBlock->setChildrenInline(childrenInline());
return cloneBlock;
}
@@ -468,10 +483,16 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
if (!isAnonymousBlock())
cloneBlock->setContinuation(oldCont);
- // Now take all of the children from beforeChild to the end and remove
- // them from |this| and place them in the clone.
if (!beforeChild && isAfterContent(lastChild()))
beforeChild = lastChild();
+
+ // If we are moving inline children from |this| to cloneBlock, then we need
+ // to clear our line box tree.
+ if (beforeChild && childrenInline())
+ deleteLineBoxTree();
+
+ // Now take all of the children from beforeChild to the end and remove
+ // them from |this| and place them in the clone.
moveChildrenTo(cloneBlock, beforeChild, 0, true);
// Hook |clone| up as the continuation of the middle block.
@@ -494,7 +515,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
cloneBlock = blockCurr->clone();
// Insert our child clone as the first child.
- cloneBlock->children()->appendChildNode(cloneBlock, cloneChild);
+ cloneBlock->addChildIgnoringContinuation(cloneChild, 0);
// Hook the clone up as a continuation of |curr|. Note we do encounter
// anonymous blocks possibly as we walk up the block chain. When we split an
@@ -585,6 +606,9 @@ void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild)
{
+ if (beforeChild->isTablePart())
+ beforeChild = splitTablePartsAroundChild(beforeChild);
+
while (beforeChild->parent() != this) {
RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent());
if (blockToSplit->firstChild() != beforeChild) {
@@ -603,6 +627,71 @@ RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeC
return beforeChild;
}
+static void markTableForSectionAndCellRecalculation(RenderObject* child)
+{
+ RenderObject* curr = child;
+ while (!curr->isTable()) {
+ if (curr->isTableSection())
+ toRenderTableSection(curr)->setNeedsCellRecalc();
+ curr = curr->parent();
+ }
+
+ RenderTable* table = toRenderTable(curr);
+ table->setNeedsSectionRecalc();
+ table->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+static void moveAllTableChildrenTo(RenderObject* fromTablePart, RenderTable* toTable, RenderObject* startChild)
+{
+ for (RenderObject* curr = startChild; curr;) {
+ // Need to store next sibling as we won't have access to it
+ // after we are removed from table.
+ RenderObject* next = curr->nextSibling();
+ fromTablePart->removeChild(curr);
+ toTable->addChild(curr);
+ if (curr->isTableSection())
+ toRenderTableSection(curr)->setNeedsCellRecalc();
+ curr->setNeedsLayoutAndPrefWidthsRecalc();
+ curr = next;
+ }
+
+ // This marks fromTable for section and cell recalculation.
+ markTableForSectionAndCellRecalculation(fromTablePart);
+
+ // startChild is now part of toTable. This marks toTable for section and cell recalculation.
+ markTableForSectionAndCellRecalculation(startChild);
+}
+
+RenderObject* RenderBlock::splitTablePartsAroundChild(RenderObject* beforeChild)
+{
+ ASSERT(beforeChild->isTablePart());
+
+ while (beforeChild->parent() != this) {
+ RenderObject* tablePartToSplit = beforeChild->parent();
+ if (!tablePartToSplit->isTablePart() && !tablePartToSplit->isTable())
+ break;
+ if (tablePartToSplit->firstChild() != beforeChild) {
+ // Get our table container.
+ RenderObject* curr = tablePartToSplit;
+ while (!curr->isTable())
+ curr = curr->parent();
+ RenderTable* table = toRenderTable(curr);
+
+ // Create an anonymous table container next to our table container.
+ RenderBlock* parentBlock = toRenderBlock(table->parent());
+ RenderTable* postTable = parentBlock->createAnonymousTable();
+ parentBlock->children()->insertChildNode(parentBlock, postTable, table->nextSibling());
+
+ // Move all the children from beforeChild to the newly created anonymous table container.
+ moveAllTableChildrenTo(tablePartToSplit, postTable, beforeChild);
+
+ beforeChild = postTable;
+ } else
+ beforeChild = tablePartToSplit;
+ }
+ return beforeChild;
+}
+
void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
{
RenderBlock* pre = 0;
@@ -669,22 +758,17 @@ RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
RenderBlock* columnsBlockAncestor = 0;
if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
&& !newChild->isFloatingOrPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
- if (style()->specifiesColumns())
- columnsBlockAncestor = this;
- else if (!isInline() && parent() && parent()->isRenderBlock()) {
- columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false);
-
- if (columnsBlockAncestor) {
- // Make sure that none of the parent ancestors have a continuation.
- // If yes, we do not want split the block into continuations.
- RenderObject* curr = this;
- while (curr && curr != columnsBlockAncestor) {
- if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
- columnsBlockAncestor = 0;
- break;
- }
- curr = curr->parent();
+ columnsBlockAncestor = containingColumnsBlock(false);
+ if (columnsBlockAncestor) {
+ // Make sure that none of the parent ancestors have a continuation.
+ // If yes, we do not want split the block into continuations.
+ RenderObject* curr = this;
+ while (curr && curr != columnsBlockAncestor) {
+ if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
+ columnsBlockAncestor = 0;
+ break;
}
+ curr = curr->parent();
}
}
}
@@ -697,35 +781,48 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
if (!beforeChild)
beforeChild = afterPseudoElementRenderer();
- // If the requested beforeChild is not one of our children, then this is because
- // there is an anonymous container within this object that contains the beforeChild.
if (beforeChild && beforeChild->parent() != this) {
- RenderObject* beforeChildAnonymousContainer = anonymousContainer(beforeChild);
- ASSERT(beforeChildAnonymousContainer);
- ASSERT(beforeChildAnonymousContainer->isAnonymous());
-
- if (beforeChildAnonymousContainer->isAnonymousBlock()) {
- // Insert the child into the anonymous block box instead of here.
- if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
- beforeChild->parent()->addChild(newChild, beforeChild);
- else
- addChild(newChild, beforeChild->parent());
- return;
- }
+ RenderObject* beforeChildContainer = beforeChild->parent();
+ while (beforeChildContainer->parent() != this)
+ beforeChildContainer = beforeChildContainer->parent();
+ ASSERT(beforeChildContainer);
+
+ if (beforeChildContainer->isAnonymous()) {
+ // If the requested beforeChild is not one of our children, then this is because
+ // there is an anonymous container within this object that contains the beforeChild.
+ RenderObject* beforeChildAnonymousContainer = beforeChildContainer;
+ if (beforeChildAnonymousContainer->isAnonymousBlock()) {
+ // Insert the child into the anonymous block box instead of here.
+ if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
+ beforeChild->parent()->addChild(newChild, beforeChild);
+ else
+ addChild(newChild, beforeChild->parent());
+ return;
+ }
- ASSERT(beforeChildAnonymousContainer->isTable());
- if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
- || (newChild->isTableCaption())
- || newChild->isTableSection()
- || newChild->isTableRow()
- || newChild->isTableCell()) {
- // Insert into the anonymous table.
- beforeChildAnonymousContainer->addChild(newChild, beforeChild);
- return;
- }
+ ASSERT(beforeChildAnonymousContainer->isTable());
+ if (newChild->isTablePart()) {
+ // Insert into the anonymous table.
+ beforeChildAnonymousContainer->addChild(newChild, beforeChild);
+ return;
+ }
+
+ beforeChild = splitTablePartsAroundChild(beforeChild);
- // Go on to insert before the anonymous table.
- beforeChild = beforeChildAnonymousContainer;
+ ASSERT(beforeChild->parent() == this);
+ if (beforeChild->parent() != this) {
+ // We should never reach here. If we do, we need to use the
+ // safe fallback to use the topmost beforeChild container.
+ beforeChild = beforeChildContainer;
+ }
+ } else {
+ // We will reach here when beforeChild is a run-in element.
+ // If run-in element precedes a block-level element, it becomes the
+ // the first inline child of that block level element. The insertion
+ // point will be before that block-level element.
+ ASSERT(beforeChild->isRunIn());
+ beforeChild = beforeChildContainer;
+ }
}
// Check for a spanning element in columns.
@@ -885,23 +982,27 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
return rootBox;
}
-void RenderBlock::moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
+void RenderBlock::moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
{
ASSERT(this == child->parent());
- ASSERT(!beforeChild || to == beforeChild->parent());
- to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
+ ASSERT(!beforeChild || toBlock == beforeChild->parent());
+ if (fullRemoveInsert) {
+ // Takes care of adding the new child correctly if toBlock and fromBlock
+ // have different kind of children (block vs inline).
+ toBlock->addChildIgnoringContinuation(children()->removeChildNode(this, child), beforeChild);
+ } else
+ toBlock->children()->insertChildNode(toBlock, children()->removeChildNode(this, child, false), beforeChild, false);
}
-void RenderBlock::moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
+void RenderBlock::moveChildrenTo(RenderBlock* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
{
- ASSERT(!beforeChild || to == beforeChild->parent());
- RenderObject* nextChild = startChild;
- while (nextChild && nextChild != endChild) {
- RenderObject* child = nextChild;
- nextChild = child->nextSibling();
- to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
- if (child == endChild)
- return;
+ ASSERT(!beforeChild || toBlock == beforeChild->parent());
+
+ for (RenderObject* child = startChild; child && child != endChild; ) {
+ // Save our next sibling as moveChildTo will clear it.
+ RenderObject* nextSibling = child->nextSibling();
+ moveChildTo(toBlock, child, beforeChild, fullRemoveInsert);
+ child = nextSibling;
}
}
@@ -1025,11 +1126,15 @@ void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* c
parent->setNeedsLayoutAndPrefWidthsRecalc();
parent->setChildrenInline(child->childrenInline());
RenderObject* nextSibling = child->nextSibling();
+
+ RenderFlowThread* childFlowThread = child->enclosingRenderFlowThread();
RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));
anonBlock->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
// Delete the now-empty block's lines and nuke it.
if (!parent->documentBeingDestroyed())
anonBlock->deleteLineBoxTree();
+ if (childFlowThread && !parent->documentBeingDestroyed())
+ childFlowThread->removeFlowChildInfo(anonBlock);
anonBlock->destroy();
}
@@ -1419,7 +1524,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
if (hasOverflowClip()) {
// Adjust repaint rect for scroll offset
- repaintRect.move(-layer()->scrolledContentOffset());
+ repaintRect.move(-scrolledContentOffset());
// Don't allow this rect to spill out of our overflow box.
repaintRect.intersect(LayoutRect(LayoutPoint(), size()));
@@ -1427,7 +1532,6 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh
// Make sure the rect is still non-empty after intersecting for overflow above
if (!repaintRect.isEmpty()) {
- // FIXME: Might need rounding once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021
repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
if (hasReflection())
repaintRectangle(reflectedRect(repaintRect));
@@ -1488,6 +1592,9 @@ void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeF
// Add visual overflow from theme.
addVisualOverflowFromTheme();
+
+ if (isRenderFlowThread())
+ enclosingRenderFlowThread()->computeOverflowStateForRegions(oldClientAfterEdge);
}
void RenderBlock::addOverflowFromBlockChildren()
@@ -1591,7 +1698,7 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
// for by simply calling canCollapseWithMarginBefore. See
// http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
// an example of this scenario.
- LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? 0 : marginInfo.margin();
+ LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? zeroLayoutUnit : marginInfo.margin();
setLogicalHeight(logicalHeight() + marginOffset);
positionNewFloats();
setLogicalHeight(logicalHeight() - marginOffset);
@@ -1893,7 +2000,6 @@ LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const Re
if (childMarginStart < 0)
startOff += childMarginStart;
newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
- // FIXME: Needs to use epsilon once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021
} else if (startOff != startPosition) {
// The object is shifting to the "end" side of the block. The object might be centered, so we need to
// recalculate our inline direction margins. Note that the containing block content
@@ -2440,7 +2546,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
// z-index. We paint after we painted the background/border, so that the scrollbars will
// sit above the background/border.
if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
- layer()->paintOverflowControls(paintInfo.context, adjustedPaintOffset, paintInfo.rect);
+ layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
}
void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
@@ -2463,9 +2569,9 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
bool antialias = shouldAntialiasLines(paintInfo.context);
if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
- LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
+ LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();
LayoutUnit ruleAdd = logicalLeftOffsetForContent();
- LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
+ LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth();
LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
BoxSide boxSide = isHorizontalWritingMode()
? style()->isLeftToRightDirection() ? BSLeft : BSRight
@@ -2487,7 +2593,8 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
- drawLineForBoxSide(paintInfo.context, ruleLeft, ruleTop, ruleRight, ruleBottom, boxSide, ruleColor, ruleStyle, 0, 0, antialias);
+ IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
+ drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
}
ruleLogicalLeft = currLogicalLeftOffset;
@@ -2512,7 +2619,8 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain
for (unsigned i = 1; i < colCount; i++) {
ruleRect.move(step);
- drawLineForBoxSide(paintInfo.context, ruleRect.x(), ruleRect.y(), ruleRect.maxX(), ruleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
+ IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
+ drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
}
}
}
@@ -2540,7 +2648,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& p
}
colRect.moveBy(paintOffset);
PaintInfo info(paintInfo);
- info.rect.intersect(colRect);
+ info.rect.intersect(pixelSnappedIntRect(colRect));
if (!info.rect.isEmpty()) {
GraphicsContextStateSaver stateSaver(*context);
@@ -2680,7 +2788,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
// Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
LayoutPoint scrolledOffset = paintOffset;
if (hasOverflowClip())
- scrolledOffset.move(-layer()->scrolledContentOffset());
+ scrolledOffset.move(-scrolledContentOffset());
// 2. paint contents
if (paintPhase != PaintPhaseSelfOutline) {
@@ -2928,7 +3036,7 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC
LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());
if (hasOverflowClip())
- offsetFromRepaintContainer -= layer()->scrolledContentOffset();
+ offsetFromRepaintContainer -= scrolledContentOffset();
LayoutUnit lastTop = 0;
LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
@@ -2953,7 +3061,8 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintO
LayoutRect localBounds(gapRectsBounds);
flipForWritingMode(localBounds);
gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
- gapRectsBounds.move(layer->scrolledContentOffset());
+ if (layer->renderer()->hasOverflowClip())
+ gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
}
layer->addBlockSelectionGapsBounds(gapRectsBounds);
}
@@ -3019,7 +3128,7 @@ GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& r
r->m_renderer->width(), r->m_renderer->height());
rootBlock->flipForWritingMode(floatBox);
floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
- paintInfo->context->clipOut(floatBox);
+ paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
}
}
}
@@ -3769,7 +3878,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co
bottom = min(floatBottom, bottom);
}
- return bottom == numeric_limits<LayoutUnit>::max() ? 0 : bottom;
+ return bottom == numeric_limits<LayoutUnit>::max() ? zeroLayoutUnit : bottom;
}
LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
@@ -4087,7 +4196,7 @@ bool RenderBlock::avoidsFloats() const
return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
}
-bool RenderBlock::containsFloat(RenderBox* renderer)
+bool RenderBlock::containsFloat(RenderBox* renderer) const
{
return m_floatingObjects && m_floatingObjects->set().contains<RenderBox*, FloatingObjectHashTranslator>(renderer);
}
@@ -4166,13 +4275,11 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
}
// We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
- LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : 0;
+ LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : zeroLayoutUnit;
if (!result && child->avoidsFloats()) {
LayoutUnit newLogicalTop = logicalTop;
while (true) {
LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false);
- // FIXME: Change to use roughlyEquals when we move to float.
- // See https://bugs.webkit.org/show_bug.cgi?id=66148
if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
return newLogicalTop - logicalTop;
@@ -4193,8 +4300,6 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
child->setMarginLeft(childOldMarginLeft);
child->setMarginRight(childOldMarginRight);
- // FIXME: Change to use roughlyEquals when we move to float.
- // See https://bugs.webkit.org/show_bug.cgi?id=66148
if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset)
return newLogicalTop - logicalTop;
@@ -4245,9 +4350,8 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
if (checkChildren) {
// Hit test descendants first.
LayoutSize scrolledOffset(localOffset);
- if (hasOverflowClip()) {
- scrolledOffset -= layer()->scrolledContentOffset();
- }
+ if (hasOverflowClip())
+ scrolledOffset -= scrolledContentOffset();
// Hit test contents if we don't have columns.
if (!hasColumns()) {
@@ -4594,7 +4698,7 @@ VisiblePosition RenderBlock::positionForPoint(const LayoutPoint& point)
void RenderBlock::offsetForContents(LayoutPoint& offset) const
{
if (hasOverflowClip())
- offset += layer()->scrolledContentOffset();
+ offset += scrolledContentOffset();
if (hasColumns())
adjustPointToColumnContents(offset);
@@ -5005,6 +5109,8 @@ void RenderBlock::computePreferredLogicalWidths()
}
int scrollbarWidth = 0;
+ // FIXME: This should only be done for horizontal writing mode.
+ // For vertical writing mode, this should check overflowX and use the horizontalScrollbarHeight.
if (hasOverflowClip() && styleToUse->overflowY() == OSCROLL) {
layer()->setHasVerticalScrollbar(true);
scrollbarWidth = verticalScrollbarWidth();
@@ -5150,7 +5256,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths()
RenderStyle* styleToUse = style();
RenderBlock* containingBlock = this->containingBlock();
- LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : 0;
+ LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : zeroLayoutUnit;
// If we are at the start of a line, we want to ignore all white-space.
// Also strip spaces if we previously had text that ended in a trailing space.
@@ -5704,6 +5810,36 @@ static inline bool shouldSkipForFirstLetter(UChar c)
return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
}
+// We only honor first-letter if
+// - the firstLetterBlock can have children in the DOM and
+// - the block doesn't have any special assumption on its text children.
+// This correctly prevents form controls from honoring first-letter.
+static inline bool isSafeToCreateFirstLetterRendererOn(RenderObject* renderer)
+{
+ return (renderer->canHaveChildren()
+ && !(renderer->isDeprecatedFlexibleBox()
+ && static_cast<RenderDeprecatedFlexibleBox*>(renderer)->buttonText()));
+}
+
+static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
+{
+ RenderObject* firstLetterBlock = start;
+ while (true) {
+ bool canHaveFirstLetterRenderer = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
+ && isSafeToCreateFirstLetterRendererOn(firstLetterBlock);
+ if (canHaveFirstLetterRenderer)
+ return firstLetterBlock;
+
+ RenderObject* parentBlock = firstLetterBlock->parent();
+ if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||
+ !parentBlock->isBlockFlow())
+ return 0;
+ firstLetterBlock = parentBlock;
+ }
+
+ return 0;
+}
+
void RenderBlock::updateFirstLetter()
{
if (!document()->usesFirstLetterRules())
@@ -5714,23 +5850,8 @@ void RenderBlock::updateFirstLetter()
// FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
// an efficient way to check for that situation though before implementing anything.
- RenderObject* firstLetterBlock = this;
- bool hasPseudoStyle = false;
- while (true) {
- // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly
- // prevents form controls from honoring first-letter.
- hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
- && firstLetterBlock->canHaveChildren();
- if (hasPseudoStyle)
- break;
- RenderObject* parentBlock = firstLetterBlock->parent();
- if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||
- !parentBlock->isBlockFlow())
- break;
- firstLetterBlock = parentBlock;
- }
-
- if (!hasPseudoStyle)
+ RenderObject* firstLetterBlock = findFirstLetterBlock(this);
+ if (!firstLetterBlock)
return;
// Drill into inlines looking for our first text child.
@@ -5922,7 +6043,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,
if (block->childrenInline()) {
for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
if (++count == l)
- return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+ return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);
}
}
else {
@@ -5931,7 +6052,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,
if (shouldCheckLines(obj)) {
int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
if (result != -1)
- return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+ return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : zeroLayoutUnit);
}
else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())
normalFlowChildWithoutLines = obj;
@@ -6495,11 +6616,15 @@ LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, P
LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)
{
- bool isUnsplittable = child->isUnsplittableForPagination() || child->style()->columnBreakInside() == PBAVOID
- || child->style()->regionBreakInside() == PBAVOID;
+ bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
+ bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight;
+ bool checkRegionBreaks = inRenderFlowThread();
+ bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID)
+ || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID)
+ || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);
if (!isUnsplittable)
return logicalOffset;
- LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : 0);
+ LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : zeroLayoutUnit);
LayoutState* layoutState = view()->layoutState();
if (layoutState->m_columnInfo)
layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);