diff options
| author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
|---|---|---|
| committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
| commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
| tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/rendering/RenderBlock.cpp | |
| parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
| download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz | |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/rendering/RenderBlock.cpp')
| -rwxr-xr-x | Source/WebCore/rendering/RenderBlock.cpp | 999 |
1 files changed, 451 insertions, 548 deletions
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index d87d77226..d03463b51 100755 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -45,11 +45,11 @@ #include "RenderBoxRegionInfo.h" #include "RenderCombineText.h" #include "RenderDeprecatedFlexibleBox.h" -#include "RenderFlowThread.h" #include "RenderImage.h" #include "RenderInline.h" #include "RenderLayer.h" #include "RenderMarquee.h" +#include "RenderNamedFlowThread.h" #include "RenderRegion.h" #include "RenderReplica.h" #include "RenderTableCell.h" @@ -69,6 +69,29 @@ namespace WebCore { using namespace HTMLNames; +struct SameSizeAsRenderBlock : public RenderBox { + void* pointers[3]; + RenderObjectChildList children; + RenderLineBoxList lineBoxes; + uint32_t bitfields; +}; + +COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small); + +struct SameSizeAsFloatingObject { + void* pointers[2]; + LayoutRect rect; + int paginationStrut; + uint32_t bitfields : 8; +}; + +COMPILE_ASSERT(sizeof(RenderBlock::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small); + +struct SameSizeAsMarginInfo { + uint32_t bitfields : 16; + LayoutUnit margins[2]; +}; + typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap; static ColumnInfoMap* gColumnInfoMap = 0; @@ -167,8 +190,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() : zeroLayoutUnit; - m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : zeroLayoutUnit; + m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : ZERO_LAYOUT_UNIT; + m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : ZERO_LAYOUT_UNIT; } // ------------------------------------------------------------------------------------------------------- @@ -177,10 +200,11 @@ RenderBlock::RenderBlock(Node* node) : RenderBox(node) , m_lineHeight(-1) , m_beingDestroyed(false) - , m_hasPositionedFloats(false) , m_hasMarkupTruncation(false) { setChildrenInline(true); + COMPILE_ASSERT(sizeof(RenderBlock::FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small); + COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small); } RenderBlock::~RenderBlock() @@ -481,7 +505,8 @@ void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, Render } // Split our anonymous blocks. - RenderObject* newBeforeChild = splitAnonymousBlocksAroundChild(beforeChild); + RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild); + // Create a new anonymous box of the appropriate type. RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock(); @@ -681,94 +706,6 @@ void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, post->setNeedsLayoutAndPrefWidthsRecalc(); } -RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild) -{ - if (beforeChild->isTablePart()) - beforeChild = splitTablePartsAroundChild(beforeChild); - - while (beforeChild->parent() != this) { - RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent()); - if (blockToSplit->firstChild() != beforeChild) { - // We have to split the parentBlock into two blocks. - RenderBlock* post = createAnonymousBlockWithSameTypeAs(blockToSplit); - post->setChildrenInline(blockToSplit->childrenInline()); - RenderBlock* parentBlock = toRenderBlock(blockToSplit->parent()); - parentBlock->children()->insertChildNode(parentBlock, post, blockToSplit->nextSibling()); - blockToSplit->moveChildrenTo(post, beforeChild, 0, blockToSplit->hasLayer()); - post->setNeedsLayoutAndPrefWidthsRecalc(); - blockToSplit->setNeedsLayoutAndPrefWidthsRecalc(); - beforeChild = post; - } else - beforeChild = blockToSplit; - } - 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; @@ -780,7 +717,7 @@ void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, R block->deleteLineBoxTree(); if (beforeChild && beforeChild->parent() != this) - beforeChild = splitAnonymousBlocksAroundChild(beforeChild); + beforeChild = splitAnonymousBoxesAroundChild(beforeChild); if (beforeChild != firstChild()) { pre = block->createAnonymousColumnsBlock(); @@ -868,7 +805,13 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, // 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()) { + if (beforeChildAnonymousContainer->isAnonymousBlock() +#if ENABLE(FULLSCREEN_API) + // Full screen renderers and full screen placeholders act as anonymous blocks, not tables: + || beforeChildAnonymousContainer->isRenderFullScreen() + || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder() +#endif + ) { // Insert the child into the anonymous block box instead of here. if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild) beforeChild->parent()->addChild(newChild, beforeChild); @@ -884,7 +827,7 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, return; } - beforeChild = splitTablePartsAroundChild(beforeChild); + beforeChild = splitAnonymousBoxesAroundChild(beforeChild); ASSERT(beforeChild->parent() == this); if (beforeChild->parent() != this) { @@ -921,12 +864,19 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, // Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after // content gets properly destroyed. + bool isFirstChild = (beforeChild == firstChild()); bool isLastChild = (beforeChild == lastChild()); if (document()->usesBeforeAfterRules()) children()->updateBeforeAfterContent(this, AFTER); - if (isLastChild && beforeChild != lastChild()) - beforeChild = 0; // We destroyed the last child, so now we need to update our insertion - // point to be 0. It's just a straight append now. + if (isLastChild && beforeChild != lastChild()) { + // We destroyed the last child, so now we need to update our insertion + // point to be 0. It's just a straight append now. + beforeChild = 0; + } else if (isFirstChild && beforeChild != firstChild()) { + // If beforeChild was the last anonymous block that collapsed, + // then we need to update its value. + beforeChild = firstChild(); + } splitFlow(beforeChild, newBox, newChild, oldContinuation); return; @@ -1063,30 +1013,6 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox() return rootBox; } -void RenderBlock::moveChildTo(RenderBlock* toBlock, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert) -{ - ASSERT(this == child->parent()); - 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* toBlock, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert) -{ - 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; - } -} - void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint) { // makeChildrenNonInline takes a block whose children are *all* inline and it @@ -1214,8 +1140,8 @@ void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* c // Delete the now-empty block's lines and nuke it. if (!parent->documentBeingDestroyed()) anonBlock->deleteLineBoxTree(); - if (childFlowThread && !parent->documentBeingDestroyed()) - childFlowThread->removeFlowChildInfo(anonBlock); + if (!parent->documentBeingDestroyed() && childFlowThread && childFlowThread->isRenderNamedFlowThread()) + toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock); anonBlock->destroy(); } @@ -1241,7 +1167,7 @@ void RenderBlock::removeChild(RenderObject* oldChild) // to clear out inherited column properties by just making a new style, and to also clear the // column span flag if it is set. ASSERT(!inlineChildrenBlock->continuation()); - RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK); children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlock->hasLayer()); inlineChildrenBlock->setStyle(newStyle); @@ -1371,18 +1297,12 @@ void RenderBlock::finishDelayUpdateScrollInfo() void RenderBlock::updateScrollInfoAfterLayout() { - if (!hasOverflowClip()) - return; - - if (!hasLayer()) { - updateCachedSizeForOverflowClip(); - return; + if (hasOverflowClip()) { + if (gDelayUpdateScrollInfo) + gDelayedUpdateScrollInfoSet->add(this); + else + layer()->updateScrollInfoAfterLayout(); } - - if (gDelayUpdateScrollInfo) - gDelayedUpdateScrollInfoSet->add(this); - else - layer()->updateScrollInfoAfterLayout(); } void RenderBlock::layout() @@ -1409,7 +1329,7 @@ void RenderBlock::computeInitialRegionRangeForBlock() // effectively clamped to our region range. LayoutUnit oldHeight = logicalHeight(); LayoutUnit oldLogicalTop = logicalTop(); - setLogicalHeight(numeric_limits<LayoutUnit>::max() / 2); + setLogicalHeight(MAX_LAYOUT_UNIT / 2); computeLogicalHeight(); enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage()); setLogicalHeight(oldHeight); @@ -1423,7 +1343,18 @@ void RenderBlock::computeRegionRangeForBlock() enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage()); } -void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight, BlockLayoutPass layoutPass) +bool RenderBlock::recomputeLogicalWidth() +{ + LayoutUnit oldWidth = logicalWidth(); + LayoutUnit oldColumnWidth = desiredColumnWidth(); + + computeLogicalWidth(); + calcColumnWidth(); + + return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth(); +} + +void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight) { ASSERT(needsLayout()); @@ -1435,23 +1366,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh LayoutRepainter repainter(*this, everHadLayout() && checkForRepaintDuringLayout()); - LayoutUnit oldWidth = logicalWidth(); - LayoutUnit oldColumnWidth = desiredColumnWidth(); - - computeLogicalWidth(); - calcColumnWidth(); + if (recomputeLogicalWidth()) + relayoutChildren = true; m_overflow.clear(); - if (oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth()) - relayoutChildren = true; - - // If nothing changed about our floating positioned objects, let's go ahead and try to place them as - // floats to avoid doing two passes. - BlockLayoutPass floatsLayoutPass = layoutPass; - if (floatsLayoutPass == NormalLayoutPass && !relayoutChildren && !positionedFloatsNeedRelayout()) - floatsLayoutPass = PositionedFloatLayoutPass; - clearFloats(floatsLayoutPass); + clearFloats(); LayoutUnit previousHeight = logicalHeight(); setLogicalHeight(0); @@ -1556,7 +1476,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isBlockFlow() && !child->isFloatingOrPositioned()) { RenderBlock* block = toRenderBlock(child); - if (block->lowestFloatLogicalBottomIncludingPositionedFloats() + block->logicalTop() > newHeight) + if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight) addOverhangingFloats(block, false); } } @@ -1566,7 +1486,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh if (previousHeight != newHeight) relayoutChildren = true; - bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot()); + layoutPositionedObjects(relayoutChildren || isRoot()); computeRegionRangeForBlock(); @@ -1611,7 +1531,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline)); - if (hasOverflowClipWithLayer()) { + if (hasOverflowClip()) { // Adjust repaint rect for scroll offset repaintRect.move(-scrolledContentOffset()); @@ -1627,11 +1547,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeigh } } - if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) { - setChildNeedsLayout(true, false); - layoutBlock(false, pageLogicalHeight, PositionedFloatLayoutPass); - } else - setNeedsLayout(false); + setNeedsLayout(false); } void RenderBlock::addOverflowFromChildren() @@ -1703,7 +1619,7 @@ void RenderBlock::addOverflowFromFloats() FloatingObjectSetIterator end = floatingObjectSet.end(); for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { FloatingObject* r = *it; - if (r->m_isDescendant && !r->m_renderer->isPositioned()) + if (r->isDescendant()) addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r))); } return; @@ -1734,7 +1650,7 @@ void RenderBlock::addVisualOverflowFromTheme() if (!style()->hasAppearance()) return; - IntRect inflatedRect = borderBoxRect(); + IntRect inflatedRect = pixelSnappedBorderBoxRect(); theme()->adjustRepaintRect(this, inflatedRect); addVisualOverflow(inflatedRect); } @@ -1772,7 +1688,7 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg if (childLayer->staticBlockPosition() != logicalTop) { childLayer->setStaticBlockPosition(logicalTop); if (hasStaticBlockPosition) - child->setChildNeedsLayout(true, false); + child->setChildNeedsLayout(true, MarkOnlyThis); } } @@ -1791,7 +1707,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() ? zeroLayoutUnit : marginInfo.margin(); + LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? ZERO_LAYOUT_UNIT : marginInfo.margin(); setLogicalHeight(logicalHeight() + marginOffset); positionNewFloats(); setLogicalHeight(logicalHeight() - marginOffset); @@ -1833,14 +1749,22 @@ bool RenderBlock::handleRunInChild(RenderBox* child) // block. if (!child->isRunIn() || !child->childrenInline()) return false; + // FIXME: We don't handle non-block elements with run-in for now. if (!child->isRenderBlock()) - return false; + return false; + // Run-in child shouldn't intrude into the sibling block if it is part of a // continuation chain. In that case, treat it as a normal block. if (child->isElementContinuation() || child->virtualContinuation()) return false; + // Check if this node is allowed to run-in. E.g. <select> expects its renderer to + // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in. + Node* runInNode = child->node(); + if (runInNode && runInNode->hasTagName(selectTag)) + return false; + RenderBlock* blockRunIn = toRenderBlock(child); RenderObject* curr = blockRunIn->nextSibling(); if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned()) @@ -1862,14 +1786,13 @@ bool RenderBlock::handleRunInChild(RenderBox* child) children()->removeChildNode(this, blockRunIn); // Create an inline. - Node* runInNode = blockRunIn->node(); RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document()); inlineRunIn->setStyle(blockRunIn->style()); // Move the nodes from the old child to the new child for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) { RenderObject* nextSibling = runInChild->nextSibling(); - blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false); + blockRunIn->children()->removeChildNode(blockRunIn, runInChild); inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content. runInChild = nextSibling; } @@ -2080,7 +2003,7 @@ LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const Margi } LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, - LayoutUnit childLogicalWidth, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) + RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) { LayoutUnit startPosition = startOffsetForContent(region, offsetFromLogicalTopOfFirstPage); @@ -2097,24 +2020,9 @@ 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. - } 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 - // width computation will take into account the delta between |startOff| and |startPosition| - // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection| - // function. - LayoutUnit oldMarginStart = marginStartForChild(child); - LayoutUnit oldMarginEnd = marginEndForChild(child); - RenderBox* mutableChild = const_cast<RenderBox*>(child); - mutableChild->computeInlineDirectionMargins(this, - availableLogicalWidthForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage), childLogicalWidth); - newPosition = startOff + marginStartForChild(child); - if (inRenderFlowThread()) { - setMarginStartForChild(mutableChild, oldMarginStart); - setMarginEndForChild(mutableChild, oldMarginEnd); - } - } - + } else if (startOff != startPosition) + newPosition = startOff + childMarginStart; + return newPosition - oldPosition; } @@ -2132,7 +2040,7 @@ void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child) // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need // to shift over as necessary to dodge any floats that might get in the way. if (child->avoidsFloats() && containsFloats() && !inRenderFlowThread()) - newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child), logicalWidthForChild(child)); + newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child)); setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta); } @@ -2211,7 +2119,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloa while (box != this) { if (box->normalChildNeedsLayout()) break; - box->setChildNeedsLayout(true, false); + box->setChildNeedsLayout(true, MarkOnlyThis); box = box->containingBlock(); ASSERT(box); if (!box) @@ -2253,13 +2161,12 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloa // Make sure we layout children if they need it. // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into // an auto value. Add a method to determine this, so that we can avoid the relayout. - RenderStyle* childStyle = child->style(); - if (relayoutChildren || ((childStyle->logicalHeight().isPercent() || childStyle->logicalMinHeight().isPercent() || childStyle->logicalMaxHeight().isPercent()) && !isRenderView())) - child->setChildNeedsLayout(true, false); + if (relayoutChildren || (child->hasRelativeLogicalHeight() && !isRenderView())) + child->setChildNeedsLayout(true, MarkOnlyThis); // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths. if (relayoutChildren && child->needsPreferredWidthsRecalculation()) - child->setPreferredLogicalWidthsDirty(true, false); + child->setPreferredLogicalWidthsDirty(true, MarkOnlyThis); // Handle the four types of special elements first. These include positioned content, floating content, compacts and // run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks. @@ -2313,7 +2220,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) { // If an element might be affected by the presence of floats, then always mark it for // layout. - LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottomIncludingPositionedFloats()); + LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom()); if (fb > logicalTopEstimate) markDescendantsWithFloats = true; } @@ -2322,7 +2229,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay if (markDescendantsWithFloats) childRenderBlock->markAllDescendantsWithFloatsForLayout(); if (!child->isWritingModeRoot()) - previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottomIncludingPositionedFloats()); + previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom()); } if (!child->needsLayout()) @@ -2357,7 +2264,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, Lay // When the child shifts to clear an item, its width can // change (because it has more available line width). // So go ahead and mark the item as dirty. - child->setChildNeedsLayout(true, false); + child->setChildNeedsLayout(true, MarkOnlyThis); } if (childRenderBlock) { @@ -2461,8 +2368,8 @@ bool RenderBlock::simplifiedLayout() simplifiedNormalFlowLayout(); // Lay out our positioned objects if our positioned child bit is set. - if (posChildNeedsLayout() && layoutPositionedObjects(false)) - return false; // If a positioned float is causing our normal flow to change, then we have to bail and do a full layout. + if (posChildNeedsLayout()) + layoutPositionedObjects(false); // Recompute our overflow information. // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only @@ -2482,41 +2389,14 @@ bool RenderBlock::simplifiedLayout() return true; } -bool RenderBlock::positionedFloatsNeedRelayout() -{ - if (!hasPositionedFloats()) - return false; - - RenderBox* positionedObject; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - positionedObject = *it; - if (!positionedObject->isFloating()) - continue; - - if (positionedObject->needsLayout()) - return true; - - if (positionedObject->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && positionedObject->parent() != this && positionedObject->parent()->isBlockFlow()) - return true; - - if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset())) - return true; - } - - return false; -} - -bool RenderBlock::layoutPositionedObjects(bool relayoutChildren) +void RenderBlock::layoutPositionedObjects(bool relayoutChildren) { if (!m_positionedObjects) - return false; + return; if (hasColumns()) view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns. - bool didFloatingBoxRelayout = false; - RenderBox* r; Iterator end = m_positionedObjects->end(); for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { @@ -2526,20 +2406,15 @@ bool RenderBlock::layoutPositionedObjects(bool relayoutChildren) // objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is // positioned explicitly) this should not incur a performance penalty. if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this)) - r->setChildNeedsLayout(true, false); + r->setChildNeedsLayout(true, MarkOnlyThis); // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths. if (relayoutChildren && r->needsPreferredWidthsRecalculation()) - r->setPreferredLogicalWidthsDirty(true, false); + r->setPreferredLogicalWidthsDirty(true, MarkOnlyThis); if (!r->needsLayout()) r->markForPaginationRelayoutIfNeeded(); - // FIXME: Technically we could check the old placement and the new placement of the box and only invalidate if - // the margin box of the object actually changed. - if (r->needsLayout() && r->isFloating()) - didFloatingBoxRelayout = true; - // We don't have to do a full layout. We just have to update our position. Try that first. If we have shrink-to-fit width // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout. if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly()) @@ -2556,20 +2431,26 @@ bool RenderBlock::layoutPositionedObjects(bool relayoutChildren) r->computeLogicalWidth(); oldLogicalTop = logicalTopForChild(r); } - - r->layoutIfNeeded(); + r->layoutIfNeeded(); + + // Adjust the static position of a center-aligned inline positioned object with a block child now that the child's width has been computed. + if (!r->parent()->isRenderView() && r->parent()->isRenderBlock() && r->firstChild() && r->style()->position() == AbsolutePosition + && r->style()->isOriginalDisplayInlineType() && (r->style()->textAlign() == CENTER || r->style()->textAlign() == WEBKIT_CENTER)) { + RenderBlock* block = toRenderBlock(r->parent()); + LayoutUnit blockHeight = block->logicalHeight(); + block->setStaticInlinePositionForChild(r, blockHeight, block->startAlignedOffsetForLine(r, blockHeight, false)); + } + // Lay out again if our estimate was wrong. if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) { - r->setChildNeedsLayout(true, false); + r->setChildNeedsLayout(true, MarkOnlyThis); r->layoutIfNeeded(); } } if (hasColumns()) view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work. - - return didFloatingBoxRelayout; } void RenderBlock::markPositionedObjectsForLayout() @@ -2591,7 +2472,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded() return; if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset())) - setChildNeedsLayout(true, false); + setChildNeedsLayout(true, MarkOnlyThis); } void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants) @@ -2611,7 +2492,7 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants) // Only repaint the object if it is overhanging, is not in its own layer, and // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter // condition is replaced with being a descendant of us. - if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) { + if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->shouldPaint()) && !r->m_renderer->hasSelfPaintingLayer()) { r->m_renderer->repaint(); r->m_renderer->repaintOverhangingFloats(); } @@ -2644,7 +2525,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with // z-index. We paint after we painted the background/border, so that the scrollbars will // sit above the background/border. - if (hasOverflowClipWithLayer() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this)) + if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this)) layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect); } @@ -2668,9 +2549,9 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& pain bool antialias = shouldAntialiasLines(paintInfo.context); if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { - LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth(); + LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); LayoutUnit ruleAdd = logicalLeftOffsetForContent(); - LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? zeroLayoutUnit : contentLogicalWidth(); + LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? ZERO_LAYOUT_UNIT : contentLogicalWidth(); LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth(); BoxSide boxSide = isHorizontalWritingMode() ? style()->isLeftToRightDirection() ? BSLeft : BSRight @@ -2780,13 +2661,10 @@ void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOf if (document()->didLayoutWithPendingStylesheets() && !isRenderView()) return; - // We don't want to hand off painting in the line box tree with the accumulated error of the render tree, as this will cause - // us to mess up painting aligned things (such as underlines in text) with both the render tree and line box tree's error. - LayoutPoint roundedPaintOffset = roundedIntPoint(paintOffset); if (childrenInline()) - m_lineBoxes.paint(this, paintInfo, roundedPaintOffset); + m_lineBoxes.paint(this, paintInfo, paintOffset); else - paintChildren(paintInfo, roundedPaintOffset); + paintChildren(paintInfo, paintOffset); } void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset) @@ -2918,7 +2796,10 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs // 6. paint continuation outlines. if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) { RenderInline* inlineCont = inlineElementContinuation(); - if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) { + // FIXME: For now, do not add continuations for outline painting by our containing block if we are a relative positioned + // anonymous block (i.e. have our own layer). This is because a block depends on renderers in its continuation table being + // in the same layer. + if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE && !hasLayer()) { RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer()); RenderBlock* cb = containingBlock(); @@ -2970,7 +2851,7 @@ void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffs for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { FloatingObject* r = *it; // Only paint the object if our m_shouldPaint flag is set. - if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) { + if (r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()) { PaintInfo currentPaintInfo(paintInfo); currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y())); @@ -3282,8 +3163,8 @@ GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPo // Now paint the gaps for the lines. for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) { - LayoutUnit selTop = curr->selectionTop(); - LayoutUnit selHeight = curr->selectionHeight(); + LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock(); + LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock(); if (!containsStart && !lastSelectedLine && selectionState() != SelectionStart && selectionState() != SelectionBoth) @@ -3475,6 +3356,38 @@ LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, Layo return logicalRight; } +RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const +{ + if (isSelectionRoot()) + return 0; + + const RenderBox* object = this; + RenderObject* sibling; + do { + sibling = object->previousSibling(); + while (sibling && (!sibling->isRenderBlock() || toRenderBlock(sibling)->isSelectionRoot())) + sibling = sibling->previousSibling(); + + offset -= LayoutSize(object->logicalLeft(), object->logicalTop()); + object = object->parentBox(); + } while (!sibling && object && object->isRenderBlock() && !toRenderBlock(object)->isSelectionRoot()); + + if (!sibling) + return 0; + + RenderBlock* beforeBlock = toRenderBlock(sibling); + + offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop()); + + RenderObject* child = beforeBlock->lastChild(); + while (child && child->isRenderBlock()) { + beforeBlock = toRenderBlock(child); + offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop()); + child = beforeBlock->lastChild(); + } + return beforeBlock; +} + void RenderBlock::insertPositionedObject(RenderBox* o) { ASSERT(!isAnonymousBlock()); @@ -3487,12 +3400,18 @@ void RenderBlock::insertPositionedObject(RenderBox* o) m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet); m_positionedObjects->add(o); + + if (o->style()->position() == FixedPosition && view()) + view()->insertFixedPositionedObject(o); } void RenderBlock::removePositionedObject(RenderBox* o) { if (m_positionedObjects) m_positionedObjects->remove(o); + + if (view()) + view()->removeFixedPositionedObject(o); } void RenderBlock::removePositionedObjects(RenderBlock* o) @@ -3510,7 +3429,7 @@ void RenderBlock::removePositionedObjects(RenderBlock* o) r = *it; if (!o || r->isDescendantOf(o)) { if (o) - r->setChildNeedsLayout(true, false); + r->setChildNeedsLayout(true, MarkOnlyThis); // It is parent blocks job to add positioned child to positioned objects list of its containing block // Parent layout needs to be invalidated to ensure this happens. @@ -3549,23 +3468,21 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o) // Our location is irrelevant if we're unsplittable or no pagination is in effect. // Just go ahead and lay out the float. - if (!o->isPositioned()) { - bool isChildRenderBlock = o->isRenderBlock(); - if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged()) - o->setChildNeedsLayout(true, false); + bool isChildRenderBlock = o->isRenderBlock(); + if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged()) + o->setChildNeedsLayout(true, MarkOnlyThis); - bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout(); - if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root. - o->layoutIfNeeded(); - else { - o->computeLogicalWidth(); - o->computeBlockDirectionMargins(this); - } + bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout(); + if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root. + o->layoutIfNeeded(); + else { + o->computeLogicalWidth(); + o->computeBlockDirectionMargins(this); } setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o)); - newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will. - newObj->m_isDescendant = true; + newObj->setShouldPaint(!o->hasSelfPaintingLayer()); // If a layer exists, the float will paint itself. Otherwise someone else will. + newObj->setIsDescendant(true); newObj->m_renderer = o; m_floatingObjects->add(newObj); @@ -3585,8 +3502,8 @@ void RenderBlock::removeFloatingObject(RenderBox* o) LayoutUnit logicalBottom = logicalBottomForFloat(r); // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. - if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == numeric_limits<LayoutUnit>::max()) - logicalBottom = numeric_limits<LayoutUnit>::max(); + if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == MAX_LAYOUT_UNIT) + logicalBottom = MAX_LAYOUT_UNIT; else { // 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 @@ -3714,9 +3631,8 @@ bool RenderBlock::positionNewFloats() for (; it != end; ++it) { FloatingObject* floatingObject = *it; // The containing block is responsible for positioning floats, so if we have floats in our - // list that come from somewhere else, do not attempt to position them. Also don't attempt to handle - // positioned floats, since the positioning layout code handles those. - if (floatingObject->renderer()->containingBlock() != this || floatingObject->renderer()->isPositioned()) + // list that come from somewhere else, do not attempt to position them. + if (floatingObject->renderer()->containingBlock() != this) continue; RenderBox* childBox = floatingObject->renderer(); @@ -3765,7 +3681,7 @@ bool RenderBlock::positionNewFloats() setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox)); if (childBlock) - childBlock->setChildNeedsLayout(true, false); + childBlock->setChildNeedsLayout(true, MarkOnlyThis); childBox->layoutIfNeeded(); } } @@ -3786,7 +3702,7 @@ void RenderBlock::newLine(EClear clear) { positionNewFloats(); // set y position - int newY = 0; + LayoutUnit newY = 0; switch (clear) { case CLEFT: @@ -3816,7 +3732,7 @@ void RenderBlock::addPercentHeightDescendant(RenderBox* descendant) descendantSet = new HashSet<RenderBox*>; gPercentHeightDescendantsMap->set(this, descendantSet); } - bool added = descendantSet->add(descendant).second; + bool added = descendantSet->add(descendant).isNewEntry; if (!added) { ASSERT(gPercentHeightContainerMap->get(descendant)); ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this)); @@ -3902,9 +3818,12 @@ inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNe LayoutUnit RenderBlock::textIndentOffset() const { LayoutUnit cw = 0; + RenderView* renderView = 0; if (style()->textIndent().isPercent()) cw = containingBlock()->availableLogicalWidth(); - return style()->textIndent().calcMinValue(cw); + else if (style()->textIndent().isViewportPercentage()) + renderView = view(); + return minimumValueForLength(style()->textIndent(), cw, renderView); } LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const @@ -4027,7 +3946,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co if (!m_floatingObjects) return logicalHeight; - LayoutUnit bottom = numeric_limits<LayoutUnit>::max(); + LayoutUnit bottom = MAX_LAYOUT_UNIT; const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); FloatingObjectSetIterator end = floatingObjectSet.end(); for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { @@ -4037,7 +3956,7 @@ LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) co bottom = min(floatBottom, bottom); } - return bottom == numeric_limits<LayoutUnit>::max() ? zeroLayoutUnit : bottom; + return bottom == MAX_LAYOUT_UNIT ? ZERO_LAYOUT_UNIT : bottom; } LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const @@ -4062,7 +3981,7 @@ void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit l RootInlineBox* lowestDirtyLine = lastRootBox(); RootInlineBox* afterLowest = lowestDirtyLine; - while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < numeric_limits<LayoutUnit>::max()) { + while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < MAX_LAYOUT_UNIT) { afterLowest = lowestDirtyLine; lowestDirtyLine = lowestDirtyLine->prevRootBox(); } @@ -4073,40 +3992,21 @@ void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit l } } -void RenderBlock::addPositionedFloats() -{ - if (!m_positionedObjects) - return; - - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - RenderBox* positionedObject = *it; - if (!positionedObject->isFloating()) - continue; - - ASSERT(!positionedObject->needsLayout()); - - // If we're a positioned float, then we need to insert ourselves as a floating object also. We only do - // this after the positioned object has received a layout, since otherwise the dimensions and placement - // won't be correct. - FloatingObject* floatingObject = insertFloatingObject(positionedObject); - setLogicalLeftForFloat(floatingObject, logicalLeftForChild(positionedObject) - marginLogicalLeftForChild(positionedObject)); - setLogicalTopForFloat(floatingObject, logicalTopForChild(positionedObject) - marginBeforeForChild(positionedObject)); - setLogicalHeightForFloat(floatingObject, logicalHeightForChild(positionedObject) + marginBeforeForChild(positionedObject) + marginAfterForChild(positionedObject)); - - m_floatingObjects->addPlacedObject(floatingObject); - - m_hasPositionedFloats = true; - } -} - -void RenderBlock::clearFloats(BlockLayoutPass layoutPass) +void RenderBlock::clearFloats() { if (m_floatingObjects) m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); - // Clear our positioned floats boolean. - m_hasPositionedFloats = false; + HashSet<RenderBox*> oldIntrudingFloatSet; + if (!childrenInline() && m_floatingObjects) { + const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); + FloatingObjectSetIterator end = floatingObjectSet.end(); + for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { + FloatingObject* floatingObject = *it; + if (!floatingObject->isDescendant()) + oldIntrudingFloatSet.add(floatingObject->m_renderer); + } + } // Inline blocks are covered by the isReplaced() check in the avoidFloats method. if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) { @@ -4114,8 +4014,8 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) deleteAllValues(m_floatingObjects->set()); m_floatingObjects->clear(); } - if (layoutPass == PositionedFloatLayoutPass) - addPositionedFloats(); + if (!oldIntrudingFloatSet.isEmpty()) + markAllDescendantsWithFloatsForLayout(); return; } @@ -4135,9 +4035,6 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) m_floatingObjects->clear(); } - if (layoutPass == PositionedFloatLayoutPass) - addPositionedFloats(); - // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add // floats in an invalid context. This will cause a crash arising from a bad cast on the parent. // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG. @@ -4148,7 +4045,7 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted // to avoid floats. RenderBlock* parentBlock = toRenderBlock(parent()); - bool parentHasFloats = parentBlock->hasPositionedFloats(); + bool parentHasFloats = false; RenderObject* prev = previousSibling(); while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) { if (prev->isFloating()) @@ -4164,19 +4061,19 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) LayoutUnit logicalLeftOffset = 0; if (prev) logicalTopOffset -= toRenderBox(prev)->logicalTop(); - else if (!parentHasFloats) { + else { prev = parentBlock; logicalLeftOffset += parentBlock->logicalLeftOffsetForContent(); } // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space. RenderBlock* block = toRenderBlock(prev); - if (block && block->m_floatingObjects && block->lowestFloatLogicalBottomIncludingPositionedFloats() > logicalTopOffset) + if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset) addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset); if (childrenInline()) { - LayoutUnit changeLogicalTop = numeric_limits<LayoutUnit>::max(); - LayoutUnit changeLogicalBottom = numeric_limits<LayoutUnit>::min(); + LayoutUnit changeLogicalTop = MAX_LAYOUT_UNIT; + LayoutUnit changeLogicalBottom = MIN_LAYOUT_UNIT; if (m_floatingObjects) { const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); FloatingObjectSetIterator end = floatingObjectSet.end(); @@ -4218,7 +4115,7 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) RendererToFloatInfoMap::iterator end = floatMap.end(); for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) { FloatingObject* floatingObject = (*it).second; - if (!floatingObject->m_isDescendant) { + if (!floatingObject->isDescendant()) { changeLogicalTop = 0; changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject)); } @@ -4226,6 +4123,19 @@ void RenderBlock::clearFloats(BlockLayoutPass layoutPass) deleteAllValues(floatMap); markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); + } else if (!oldIntrudingFloatSet.isEmpty()) { + // If there are previously intruding floats that no longer intrude, then children with floats + // should also get layout because they might need their floating object lists cleared. + if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) + markAllDescendantsWithFloatsForLayout(); + else { + const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); + FloatingObjectSetIterator end = floatingObjectSet.end(); + for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it) + oldIntrudingFloatSet.remove((*it)->m_renderer); + if (!oldIntrudingFloatSet.isEmpty()) + markAllDescendantsWithFloatsForLayout(); + } } } @@ -4244,7 +4154,7 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) { FloatingObject* r = *childIt; - LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), numeric_limits<LayoutUnit>::max() - childLogicalTop); + LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), MAX_LAYOUT_UNIT - childLogicalTop); LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom); @@ -4261,11 +4171,11 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP // far out as we can, to the outermost block that overlaps the float, stopping only // if we hit a self-painting layer boundary. if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer()) - r->m_shouldPaint = false; + r->setShouldPaint(false); else - floatingObj->m_shouldPaint = false; - - floatingObj->m_isDescendant = true; + floatingObj->setShouldPaint(false); + + floatingObj->setIsDescendant(true); // We create the floating object list lazily. if (!m_floatingObjects) @@ -4274,19 +4184,19 @@ LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildP m_floatingObjects->add(floatingObj); } } else { - if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() && - r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) { + if (makeChildPaintOtherFloats && !r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer() + && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) { // The float is not overhanging from this block, so if it is a descendant of the child, the child should // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing // layer. // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats // it should paint. - r->m_shouldPaint = true; + r->setShouldPaint(true); } // Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the // child now. - if (r->m_isDescendant) + if (r->isDescendant()) child->addOverflowFromChild(r->m_renderer, LayoutSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r))); } } @@ -4337,7 +4247,7 @@ void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOf floatingObj->setY(floatingObj->y() + prev->marginTop()); } - floatingObj->m_shouldPaint = false; // We are not in the direct inheritance chain for this float. We will never paint it. + floatingObj->setShouldPaint(false); // We are not in the direct inheritance chain for this float. We will never paint it. floatingObj->m_renderer = r->m_renderer; // We create the floating object list lazily. @@ -4365,7 +4275,8 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove if (!everHadLayout()) return; - setChildNeedsLayout(true, !inLayout); + MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain; + setChildNeedsLayout(true, markParents); if (floatToRemove) removeFloatingObject(floatToRemove); @@ -4386,26 +4297,21 @@ void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove) { if (!m_floatingObjects) return; + const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); FloatingObjectSetIterator end = floatingObjectSet.end(); - for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { - if (logicalBottomForFloat(*it) > logicalHeight()) { + + for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) { + if (!next->isRenderBlock() || next->isFloatingOrPositioned() || toRenderBlock(next)->avoidsFloats()) + continue; + + RenderBlock* nextBlock = toRenderBlock(next); + for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { RenderBox* floatingBox = (*it)->renderer(); if (floatToRemove && floatingBox != floatToRemove) continue; - - RenderObject* next = nextSibling(); - while (next) { - if (next->isRenderBlock() && !next->isFloatingOrPositioned() && !toRenderBlock(next)->avoidsFloats()) { - RenderBlock* nextBlock = toRenderBlock(next); - if (nextBlock->containsFloat(floatingBox)) - nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox); - else - break; - } - - next = next->nextSibling(); - } + if (nextBlock->containsFloat(floatingBox)) + nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox); } } } @@ -4434,7 +4340,7 @@ 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) : zeroLayoutUnit; + LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : ZERO_LAYOUT_UNIT; if (!result && child->avoidsFloats()) { LayoutUnit newLogicalTop = logicalTop; while (true) { @@ -4474,10 +4380,10 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop) bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { - if (!scrollsOverflow() || !hasLayer()) + if (!scrollsOverflow()) return false; - return layer()->hitTestOverflowControls(result, pointInContainer - toLayoutSize(accumulatedOffset)); + return layer()->hitTestOverflowControls(result, roundedIntPoint(pointInContainer - toLayoutSize(accumulatedOffset))); } bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) @@ -4554,7 +4460,7 @@ bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& re for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) { --it; FloatingObject* floatingObject = *it; - if (floatingObject->m_shouldPaint && !floatingObject->m_renderer->hasSelfPaintingLayer()) { + if (floatingObject->shouldPaint() && !floatingObject->m_renderer->hasSelfPaintingLayer()) { LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x(); LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y(); LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset)); @@ -4884,7 +4790,10 @@ int RenderBlock::columnGap() const } void RenderBlock::calcColumnWidth() -{ +{ + if (document()->regionBasedColumnsEnabled()) + return; + // Calculate our column width and column count. // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 unsigned desiredColumnCount = 1; @@ -5018,7 +4927,7 @@ bool RenderBlock::layoutColumns(bool hasSpecifiedPageLogicalHeight, LayoutUnit p view()->layoutState()->pageLogicalOffset(borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset()); columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); } - } else if (contentLogicalHeight() > pageLogicalHeight * desiredColumnCount) { + } else if (contentLogicalHeight() > boundedMultiply(pageLogicalHeight, desiredColumnCount)) { // Now that we know the intrinsic height of the columns, we have to rebalance them. columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)contentLogicalHeight() / desiredColumnCount)); } @@ -5211,11 +5120,11 @@ void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point) ColumnInfo* colInfo = columnInfo(); LayoutUnit logicalLeft = logicalLeftOffsetForContent(); - size_t colCount = columnCount(colInfo); + unsigned colCount = columnCount(colInfo); LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth(); LayoutUnit colLogicalHeight = colInfo->columnHeight(); - for (size_t i = 0; i < colCount; ++i) { + for (unsigned i = 0; i < colCount; ++i) { // Compute the edges for a given column in the block progression direction. LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingBefore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight); if (!isHorizontalWritingMode()) @@ -5409,7 +5318,7 @@ static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result) { - LayoutUnit snappedResult = ceiledLayoutUnit(result); + LayoutUnit snappedResult = ceilf(result); preferredWidth = max(snappedResult, preferredWidth); } @@ -5420,7 +5329,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths() RenderStyle* styleToUse = style(); RenderBlock* containingBlock = this->containingBlock(); - LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : zeroLayoutUnit; + LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : ZERO_LAYOUT_UNIT; // 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. @@ -5541,7 +5450,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths() LayoutUnit ti = 0; if (!addedTextIndent) { addedTextIndent = true; - ti = styleToUse->textIndent().calcMinValue(cw); + ti = minimumValueForLength(styleToUse->textIndent(), cw, view()); childMin += ti; childMax += ti; } @@ -5612,7 +5521,7 @@ void RenderBlock::computeInlinePreferredLogicalWidths() LayoutUnit ti = 0; if (!addedTextIndent) { addedTextIndent = true; - ti = styleToUse->textIndent().calcMinValue(cw); + ti = minimumValueForLength(styleToUse->textIndent(), cw, view()); childMin+=ti; beginMin += ti; childMax+=ti; beginMax += ti; } @@ -5806,11 +5715,11 @@ LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, if (firstLine && document()->usesFirstLineRules()) { RenderStyle* s = style(firstLine); if (s != style()) - return s->computedLineHeight(); + return s->computedLineHeight(view()); } if (m_lineHeight == -1) - m_lineHeight = style()->computedLineHeight(); + m_lineHeight = style()->computedLineHeight(view()); return m_lineHeight; } @@ -5838,9 +5747,9 @@ LayoutUnit RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLi bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0) : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun()); - int baselinePos = ignoreBaseline ? LayoutUnit(-1) : lastLineBoxBaseline(); + LayoutUnit baselinePos = ignoreBaseline ? static_cast<LayoutUnit>(-1) : lastLineBoxBaseline(); - int bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth(); + LayoutUnit bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth(); if (baselinePos != -1 && baselinePos <= bottomOfContent) return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos; @@ -5993,120 +5902,67 @@ static inline RenderObject* findFirstLetterBlock(RenderBlock* start) return 0; } -void RenderBlock::updateFirstLetter() +void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* currentChild) { - if (!document()->usesFirstLetterRules()) - return; - // Don't recur - if (style()->styleType() == FIRST_LETTER) - return; - - // 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 = findFirstLetterBlock(this); - if (!firstLetterBlock) - return; + RenderObject* firstLetter = currentChild->parent(); + RenderObject* firstLetterContainer = firstLetter->parent(); + RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer); + ASSERT(firstLetter->isFloating() || firstLetter->isInline()); - // Drill into inlines looking for our first text child. - RenderObject* currChild = firstLetterBlock->firstChild(); - while (currChild) { - if (currChild->isText()) - break; - if (currChild->isListMarker()) - currChild = currChild->nextSibling(); - else if (currChild->isFloatingOrPositioned()) { - if (currChild->style()->styleType() == FIRST_LETTER) { - currChild = currChild->firstChild(); - break; - } - currChild = currChild->nextSibling(); - } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList()) - break; - else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && canHaveGeneratedChildren(currChild)) { - // We found a lower-level node with first-letter, which supersedes the higher-level style - firstLetterBlock = currChild; - currChild = currChild->firstChild(); - } + if (Node::diff(firstLetter->style(), pseudoStyle, document()) == Node::Detach) { + // The first-letter renderer needs to be replaced. Create a new renderer of the right type. + RenderObject* newFirstLetter; + if (pseudoStyle->display() == INLINE) + newFirstLetter = new (renderArena()) RenderInline(document()); else - currChild = currChild->firstChild(); - } - - if (!currChild) - return; - - // If the child already has style, then it has already been created, so we just want - // to update it. - if (currChild->parent()->style()->styleType() == FIRST_LETTER) { - RenderObject* firstLetter = currChild->parent(); - RenderObject* firstLetterContainer = firstLetter->parent(); - RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer); - ASSERT(firstLetter->isFloating() || firstLetter->isInline()); - - if (Node::diff(firstLetter->style(), pseudoStyle) == Node::Detach) { - // The first-letter renderer needs to be replaced. Create a new renderer of the right type. - RenderObject* newFirstLetter; - if (pseudoStyle->display() == INLINE) - newFirstLetter = new (renderArena()) RenderInline(document()); - else - newFirstLetter = new (renderArena()) RenderBlock(document()); - newFirstLetter->setStyle(pseudoStyle); - - // Move the first letter into the new renderer. - LayoutStateDisabler layoutStateDisabler(view()); - while (RenderObject* child = firstLetter->firstChild()) { - if (child->isText()) - toRenderText(child)->removeAndDestroyTextBoxes(); - firstLetter->removeChild(child); - newFirstLetter->addChild(child, 0); - } - - RenderTextFragment* remainingText = 0; - RenderObject* nextSibling = firstLetter->nextSibling(); - RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText(); - if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment()) - remainingText = toRenderTextFragment(remainingTextObject); - if (remainingText) { - ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText); - // Replace the old renderer with the new one. - remainingText->setFirstLetter(newFirstLetter); - toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText); - } - firstLetter->destroy(); - firstLetter = newFirstLetter; - firstLetterContainer->addChild(firstLetter, nextSibling); - } else - firstLetter->setStyle(pseudoStyle); - - for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) { - if (genChild->isText()) - genChild->setStyle(pseudoStyle); - } + newFirstLetter = new (renderArena()) RenderBlock(document()); + newFirstLetter->setStyle(pseudoStyle); + + // Move the first letter into the new renderer. + LayoutStateDisabler layoutStateDisabler(view()); + while (RenderObject* child = firstLetter->firstChild()) { + if (child->isText()) + toRenderText(child)->removeAndDestroyTextBoxes(); + firstLetter->removeChild(child); + newFirstLetter->addChild(child, 0); + } + + RenderTextFragment* remainingText = 0; + RenderObject* nextSibling = firstLetter->nextSibling(); + RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText(); + if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment()) + remainingText = toRenderTextFragment(remainingTextObject); + if (remainingText) { + ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText); + // Replace the old renderer with the new one. + remainingText->setFirstLetter(newFirstLetter); + toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText); + } + firstLetter->destroy(); + firstLetter = newFirstLetter; + firstLetterContainer->addChild(firstLetter, nextSibling); + } else + firstLetter->setStyle(pseudoStyle); - return; + for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) { + if (genChild->isText()) + genChild->setStyle(pseudoStyle); } +} - if (!currChild->isText() || currChild->isBR()) - return; - - // If the child does not already have style, we create it here. - RenderObject* firstLetterContainer = currChild->parent(); - - // Our layout state is not valid for the repaints we are going to trigger by - // adding and removing children of firstLetterContainer. - LayoutStateDisabler layoutStateDisabler(view()); - - RenderText* textObj = toRenderText(currChild); - - // Create our pseudo style now that we have our firstLetterContainer determined. +void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild) +{ + RenderObject* firstLetterContainer = currentChild->parent(); RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer); - RenderObject* firstLetter = 0; if (pseudoStyle->display() == INLINE) firstLetter = new (renderArena()) RenderInline(document()); else firstLetter = new (renderArena()) RenderBlock(document()); firstLetter->setStyle(pseudoStyle); - firstLetterContainer->addChild(firstLetter, currChild); + firstLetterContainer->addChild(firstLetter, currentChild); + + RenderText* textObj = toRenderText(currentChild); // The original string is going to be either a generated content string or a DOM node's // string. We want the original string before it got transformed in case first-letter has @@ -6159,6 +6015,63 @@ void RenderBlock::updateFirstLetter() } } +void RenderBlock::updateFirstLetter() +{ + if (!document()->usesFirstLetterRules()) + return; + // Don't recur + if (style()->styleType() == FIRST_LETTER) + return; + + // 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 = findFirstLetterBlock(this); + if (!firstLetterBlock) + return; + + // Drill into inlines looking for our first text child. + RenderObject* currChild = firstLetterBlock->firstChild(); + while (currChild) { + if (currChild->isText()) + break; + if (currChild->isListMarker()) + currChild = currChild->nextSibling(); + else if (currChild->isFloatingOrPositioned()) { + if (currChild->style()->styleType() == FIRST_LETTER) { + currChild = currChild->firstChild(); + break; + } + currChild = currChild->nextSibling(); + } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList()) + break; + else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && canHaveGeneratedChildren(currChild)) { + // We found a lower-level node with first-letter, which supersedes the higher-level style + firstLetterBlock = currChild; + currChild = currChild->firstChild(); + } else + currChild = currChild->firstChild(); + } + + if (!currChild) + return; + + // If the child already has style, then it has already been created, so we just want + // to update it. + if (currChild->parent()->style()->styleType() == FIRST_LETTER) { + updateFirstLetterStyle(firstLetterBlock, currChild); + return; + } + + if (!currChild->isText() || currChild->isBR()) + return; + + // Our layout state is not valid for the repaints we are going to trigger by + // adding and removing children of firstLetterContainer. + LayoutStateDisabler layoutStateDisabler(view()); + + createFirstLetterRenderer(firstLetterBlock, currChild); +} + // Helper methods for obtaining the last line, computing line counts and heights for line counts // (crawling into blocks). static bool shouldCheckLines(RenderObject* obj) @@ -6196,7 +6109,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()) : zeroLayoutUnit); + return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : ZERO_LAYOUT_UNIT); } } else { @@ -6205,7 +6118,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()) : zeroLayoutUnit); + return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : ZERO_LAYOUT_UNIT); } else if (!obj->isFloatingOrPositioned() && !obj->isRunIn()) normalFlowChildWithoutLines = obj; @@ -6278,7 +6191,7 @@ void RenderBlock::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { FloatingObject* r = *it; // Only examine the object if our m_shouldPaint flag is set. - if (r->m_shouldPaint) { + if (r->shouldPaint()) { LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->m_renderer->x(); LayoutUnit floatRight = floatLeft + r->m_renderer->width(); left = min(left, floatLeft); @@ -6295,11 +6208,11 @@ void RenderBlock::borderFitAdjust(LayoutRect& rect) const return; // Walk any normal flow lines to snugly fit. - LayoutUnit left = numeric_limits<LayoutUnit>::max(); - LayoutUnit right = numeric_limits<LayoutUnit>::min(); + LayoutUnit left = MAX_LAYOUT_UNIT; + LayoutUnit right = MIN_LAYOUT_UNIT; LayoutUnit oldWidth = rect.width(); adjustForBorderFit(0, left, right); - if (left != numeric_limits<LayoutUnit>::max()) { + if (left != MAX_LAYOUT_UNIT) { left = min(left, oldWidth - (borderRight() + paddingRight())); left -= (borderLeft() + paddingLeft()); @@ -6308,7 +6221,7 @@ void RenderBlock::borderFitAdjust(LayoutRect& rect) const rect.expand(-left, 0); } } - if (right != numeric_limits<LayoutUnit>::min()) { + if (right != MIN_LAYOUT_UNIT) { right = max(right, borderLeft() + paddingLeft()); right += (borderRight() + paddingRight()); @@ -6365,7 +6278,7 @@ void RenderBlock::setPaginationStrut(LayoutUnit strut) m_rareData->m_paginationStrut = strut; } -void RenderBlock::setPageLogicalOffset(int logicalOffset) +void RenderBlock::setPageLogicalOffset(LayoutUnit logicalOffset) { if (!m_rareData) { if (!logicalOffset) @@ -6513,14 +6426,23 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La switch (alignment) { case alignLeft: + if (currentStyle->isLeftToRightDirection()) + x += textIndentOffset(); break; case alignCenter: x = (x + w - (borderRight() + paddingRight())) / 2; + if (currentStyle->isLeftToRightDirection()) + x += textIndentOffset() / 2; + else + x -= textIndentOffset() / 2; break; case alignRight: x = w - (borderRight() + paddingRight()) - caretWidth; + if (!currentStyle->isLeftToRightDirection()) + x -= textIndentOffset(); break; } + x = min(x, w - borderRight() - paddingRight() - caretWidth); if (extraWidthToEndOfLine) { if (isRenderBlock()) { @@ -6593,52 +6515,13 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& a inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location())); } -RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const -{ - RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); - - RenderBlock* newBox = 0; - if (isFlexibleBox) { - newStyle->setDisplay(BOX); - newBox = new (renderArena()) RenderDeprecatedFlexibleBox(document() /* anonymous box */); - } else { - newStyle->setDisplay(BLOCK); - newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); - } - - newBox->setStyle(newStyle.release()); - return newBox; -} - -RenderBlock* RenderBlock::createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const -{ - if (otherAnonymousBlock->isAnonymousColumnsBlock()) - return createAnonymousColumnsBlock(); - if (otherAnonymousBlock->isAnonymousColumnSpanBlock()) - return createAnonymousColumnSpanBlock(); - return createAnonymousBlock(otherAnonymousBlock->style()->display() == BOX); -} - -RenderBlock* RenderBlock::createAnonymousColumnsBlock() const -{ - RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); - newStyle->inheritColumnPropertiesFrom(style()); - newStyle->setDisplay(BLOCK); - - RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); - newBox->setStyle(newStyle.release()); - return newBox; -} - -RenderBlock* RenderBlock::createAnonymousColumnSpanBlock() const +RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const { - RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style()); - newStyle->setColumnSpan(ColumnSpanAll); - newStyle->setDisplay(BLOCK); - - RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */); - newBox->setStyle(newStyle.release()); - return newBox; + if (isAnonymousColumnsBlock()) + return createAnonymousColumnsWithParentRenderer(parent); + if (isAnonymousColumnSpanBlock()) + return createAnonymousColumnSpanWithParentRenderer(parent); + return createAnonymousWithParentRendererAndDisplay(parent, style()->display()); } bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const @@ -6777,7 +6660,7 @@ LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID); if (!isUnsplittable) return logicalOffset; - LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : zeroLayoutUnit); + LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : ZERO_LAYOUT_UNIT); LayoutState* layoutState = view()->layoutState(); if (layoutState->m_columnInfo) layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight); @@ -6876,7 +6759,7 @@ LayoutUnit RenderBlock::adjustBlockChildForPagination(LayoutUnit logicalTopAfter // When the child shifts to clear an item, its width can // change (because it has more available line width). // So go ahead and mark the item as dirty. - child->setChildNeedsLayout(true, false); + child->setChildNeedsLayout(true, MarkOnlyThis); } if (childRenderBlock) { @@ -7072,20 +6955,6 @@ LayoutUnit RenderBlock::marginAfterForChild(const RenderBoxModelObject* child) c return child->marginBottom(); } -LayoutUnit RenderBlock::marginLogicalLeftForChild(const RenderBoxModelObject* child) const -{ - if (isHorizontalWritingMode()) - return child->marginLeft(); - return child->marginTop(); -} - -LayoutUnit RenderBlock::marginLogicalRightForChild(const RenderBoxModelObject* child) const -{ - if (isHorizontalWritingMode()) - return child->marginRight(); - return child->marginBottom(); -} - LayoutUnit RenderBlock::marginStartForChild(const RenderBoxModelObject* child) const { if (isHorizontalWritingMode()) @@ -7168,13 +7037,13 @@ void RenderBlock::setMarginAfterForChild(RenderBox* child, LayoutUnit margin) RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child) { - int childBeforePositive = 0; - int childBeforeNegative = 0; - int childAfterPositive = 0; - int childAfterNegative = 0; + LayoutUnit childBeforePositive = 0; + LayoutUnit childBeforeNegative = 0; + LayoutUnit childAfterPositive = 0; + LayoutUnit childAfterNegative = 0; - int beforeMargin = 0; - int afterMargin = 0; + LayoutUnit beforeMargin = 0; + LayoutUnit afterMargin = 0; RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0; @@ -7256,34 +7125,29 @@ inline void RenderBlock::FloatingObjects::clear() m_placedFloatsTree.clear(); m_leftObjectsCount = 0; m_rightObjectsCount = 0; - m_positionedObjectsCount = 0; } inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type) { if (type == FloatingObject::FloatLeft) m_leftObjectsCount++; - else if (type == FloatingObject::FloatRight) + else m_rightObjectsCount++; - else - m_positionedObjectsCount++; } inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type) { if (type == FloatingObject::FloatLeft) m_leftObjectsCount--; - else if (type == FloatingObject::FloatRight) - m_rightObjectsCount--; else - m_positionedObjectsCount--; + m_rightObjectsCount--; } inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject) { if (m_horizontalWritingMode) - return RenderBlock::FloatingObjectInterval(floatingObject->y(), floatingObject->maxY(), floatingObject); - return RenderBlock::FloatingObjectInterval(floatingObject->x(), floatingObject->maxX(), floatingObject); + return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxY(), floatingObject); + return RenderBlock::FloatingObjectInterval(floatingObject->pixelSnappedX(), floatingObject->pixelSnappedMaxX(), floatingObject); } void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject) @@ -7371,6 +7235,45 @@ TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, c return constructTextRun(context, font, string.characters(), string.length(), style, expansion, flags); } +RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display) +{ + // FIXME: Do we need to cover the new flex box here ? + // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ? + EDisplay newDisplay; + RenderBlock* newBox = 0; + if (display == BOX || display == INLINE_BOX) { + newBox = new (parent->renderArena()) RenderDeprecatedFlexibleBox(parent->document() /* anonymous box */); + newDisplay = BOX; + } else { + newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */); + newDisplay = BLOCK; + } + + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), newDisplay); + newBox->setStyle(newStyle.release()); + return newBox; +} + +RenderBlock* RenderBlock::createAnonymousColumnsWithParentRenderer(const RenderObject* parent) +{ + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK); + newStyle->inheritColumnPropertiesFrom(parent->style()); + + RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */); + newBox->setStyle(newStyle.release()); + return newBox; +} + +RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const RenderObject* parent) +{ + RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK); + newStyle->setColumnSpan(ColumnSpanAll); + + RenderBlock* newBox = new (parent->renderArena()) RenderBlock(parent->document() /* anonymous box */); + newBox->setStyle(newStyle.release()); + return newBox; +} + #ifndef NDEBUG void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj) const @@ -7388,7 +7291,7 @@ String ValueToString<int>::string(const int value) String ValueToString<RenderBlock::FloatingObject*>::string(const RenderBlock::FloatingObject* floatingObject) { - return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->x(), floatingObject->y(), floatingObject->maxX(), floatingObject->maxY()); + return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->pixelSnappedX(), floatingObject->pixelSnappedY(), floatingObject->pixelSnappedMaxX(), floatingObject->pixelSnappedMaxY()); } #endif |
