diff options
| author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
|---|---|---|
| committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
| commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
| tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebCore/rendering/RenderBlock.cpp | |
| parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
| download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz | |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebCore/rendering/RenderBlock.cpp')
| -rwxr-xr-x | Source/WebCore/rendering/RenderBlock.cpp | 349 |
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); |
