Get rid of continuations.

This is all dead code now that inlines can't contain
blocks.

R=esprehn@chromium.org

Review URL: https://codereview.chromium.org/734813004
This commit is contained in:
Ojan Vafai 2014-11-18 16:56:44 -08:00
parent 785c29ed77
commit 82ddd6096e
12 changed files with 32 additions and 1064 deletions

View File

@ -300,9 +300,9 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogically
bool ltr = renderer().style()->isLeftToRightDirection();
// Check to see if all initial lines are unconstructed. If so, then
// we know the inline began on this line (unless we are a continuation).
// we know the inline began on this line.
RenderLineBoxList* lineBoxList = rendererLineBoxes();
if (!lineBoxList->firstLineBox()->isConstructed() && !renderer().isInlineElementContinuation()) {
if (!lineBoxList->firstLineBox()->isConstructed()) {
if (renderer().style()->boxDecorationBreak() == DCLONE)
includeLeftEdge = includeRightEdge = true;
else if (ltr && lineBoxList->firstLineBox() == this)
@ -312,7 +312,6 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogically
}
if (!lineBoxList->lastLineBox()->isConstructed()) {
RenderInline& inlineFlow = toRenderInline(renderer());
bool isLastObjectOnLine = !isAnsectorAndWithinBlock(&renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(&renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
// We include the border under these conditions:
@ -324,11 +323,11 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogically
includeLeftEdge = includeRightEdge = true;
else if (ltr) {
if (!nextLineBox()
&& ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation()))
&& (lastLine || isLastObjectOnLine))
includeRightEdge = true;
} else {
if ((!prevLineBox() || prevLineBox()->isConstructed())
&& ((lastLine || isLastObjectOnLine) && !inlineFlow.continuation()))
&& (lastLine || isLastObjectOnLine))
includeLeftEdge = true;
}
}
@ -998,40 +997,10 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return;
if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
// Add ourselves to the paint info struct's list of inlines that need to paint their
// outlines.
if (renderer().style()->hasOutline() && !isRootInlineBox()) {
RenderInline& inlineFlow = toRenderInline(renderer());
RenderBlock* cb = 0;
bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation();
if (containingBlockPaintsContinuationOutline) {
// FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
// after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
// anonymous blocks. In this case, it is better to bail out and paint it ourself.
RenderBlock* enclosingAnonymousBlock = renderer().containingBlock();
if (!enclosingAnonymousBlock->isAnonymousBlock()) {
containingBlockPaintsContinuationOutline = false;
} else {
cb = enclosingAnonymousBlock->containingBlock();
for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
if (box->hasSelfPaintingLayer()) {
containingBlockPaintsContinuationOutline = false;
break;
}
}
}
}
if (containingBlockPaintsContinuationOutline) {
// Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically.
cb->addContinuationWithOutline(toRenderInline(renderer().node()->renderer()));
} else if (!inlineFlow.isInlineElementContinuation()) {
paintInfo.outlineObjects()->add(&inlineFlow);
}
}
if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline)
&& renderer().style()->hasOutline() && !isRootInlineBox()) {
RenderInline& inlineFlow = toRenderInline(renderer());
paintInfo.outlineObjects()->add(&inlineFlow);
} else if (paintInfo.phase == PaintPhaseMask) {
paintMask(paintInfo, paintOffset);
return;

View File

@ -74,8 +74,6 @@ static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0;
static TrackedContainerMap* gPositionedContainerMap = 0;
static TrackedContainerMap* gPercentHeightContainerMap = 0;
typedef WTF::HashMap<RenderBlock*, OwnPtr<ListHashSet<RenderInline*> > > ContinuationOutlineTableMap;
typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
static int gDelayUpdateScrollInfo = 0;
static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
@ -140,15 +138,6 @@ void RenderBlock::willBeDestroyed()
// properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
children()->destroyLeftoverChildren();
// Destroy our continuation before anything other than anonymous children.
// The reason we don't destroy it before anonymous children is that they may
// have continuations of their own that are anonymous children of our continuation.
RenderBoxModelObject* continuation = this->continuation();
if (continuation) {
continuation->destroy();
setContinuation(0);
}
if (!documentBeingDestroyed()) {
if (firstLineBox()) {
// We can't wait for RenderBox::destroy to clear the selection,
@ -226,17 +215,6 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
RenderBox::styleDidChange(diff, oldStyle);
RenderStyle* newStyle = style();
if (!isAnonymousBlock()) {
// Ensure that all of our continuation blocks pick up the new style.
for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
RenderBoxModelObject* nextCont = currCont->continuation();
currCont->setContinuation(0);
currCont->setStyle(newStyle);
currCont->setContinuation(nextCont);
}
}
propagateStyleToAnonymousChildren(true);
// It's possible for our border/padding to change, but for the overall logical width of the block to
@ -296,147 +274,6 @@ void RenderBlock::invalidateTreeIfNeeded(const PaintInvalidationState& paintInva
}
}
RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
{
if (beforeChild && beforeChild->parent() == this)
return this;
RenderBlock* curr = toRenderBlock(continuation());
RenderBlock* nextToLast = this;
RenderBlock* last = this;
while (curr) {
if (beforeChild && beforeChild->parent() == curr) {
if (curr->firstChild() == beforeChild)
return last;
return curr;
}
nextToLast = last;
last = curr;
curr = toRenderBlock(curr->continuation());
}
if (!beforeChild && !last->firstChild())
return nextToLast;
return last;
}
void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
RenderBlock* flow = continuationBefore(beforeChild);
ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock());
RenderBoxModelObject* beforeChildParent = 0;
if (beforeChild)
beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
else {
RenderBoxModelObject* cont = flow->continuation();
if (cont)
beforeChildParent = cont;
else
beforeChildParent = flow;
}
if (newChild->isFloatingOrOutOfFlowPositioned()) {
beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
return;
}
if (flow == beforeChildParent) {
flow->addChildIgnoringContinuation(newChild, beforeChild);
return;
}
beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
}
RenderBlock* RenderBlock::clone() const
{
RenderBlock* cloneBlock;
if (isAnonymousBlock()) {
cloneBlock = createAnonymousBlock();
cloneBlock->setChildrenInline(childrenInline());
} else {
RenderObject* cloneRenderer = toElement(node())->createRenderer(style());
cloneBlock = toRenderBlock(cloneRenderer);
cloneBlock->setStyle(style());
// 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());
}
return cloneBlock;
}
void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont)
{
// Create a clone of this inline.
RenderBlock* cloneBlock = clone();
if (!isAnonymousBlock())
cloneBlock->setContinuation(oldCont);
// 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.
if (!cloneBlock->isAnonymousBlock())
middleBlock->setContinuation(cloneBlock);
// We have been reparented and are now under the fromBlock. We need
// to walk up our block parent chain until we hit the containing anonymous columns block.
// Once we hit the anonymous columns block we're done.
RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
RenderBoxModelObject* currChild = this;
RenderObject* currChildNextSibling = currChild->nextSibling();
while (curr && curr->isDescendantOf(fromBlock) && curr != fromBlock) {
ASSERT_WITH_SECURITY_IMPLICATION(curr->isRenderBlock());
RenderBlock* blockCurr = toRenderBlock(curr);
// Create a new clone.
RenderBlock* cloneChild = cloneBlock;
cloneBlock = blockCurr->clone();
// Insert our child clone as the first child.
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
// anonymous block, there's no need to do any continuation hookup, since we haven't
// actually split a real element.
if (!blockCurr->isAnonymousBlock()) {
oldCont = blockCurr->continuation();
blockCurr->setContinuation(cloneBlock);
cloneBlock->setContinuation(oldCont);
}
// Now we need to take all of the children starting from the first child
// *after* currChild and append them all to the clone.
blockCurr->moveChildrenTo(cloneBlock, currChildNextSibling, 0, true);
// Keep walking up the chain.
currChild = curr;
currChildNextSibling = currChild->nextSibling();
curr = toRenderBoxModelObject(curr->parent());
}
// Now we are at the columns block level. We need to put the clone into the toBlock.
toBlock->children()->appendChildNode(toBlock, cloneBlock);
// Now take all the children after currChild and remove them from the fromBlock
// and put them in the toBlock.
fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true);
}
void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
{
if (beforeChild && beforeChild->parent() != this) {
@ -461,14 +298,6 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild,
}
void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
if (continuation() && !isAnonymousBlock())
addChildToContinuation(newChild, beforeChild);
else
addChildIgnoringContinuation(newChild, beforeChild);
}
void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
}
@ -484,21 +313,6 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
// FIXME(sky): Remove
}
static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
{
if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
return false;
if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
|| (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
return false;
if (!prev || !next)
return true;
return true;
}
void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child)
{
// It's possible that this block's destruction may have been triggered by the
@ -520,103 +334,15 @@ void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock*
void RenderBlock::removeChild(RenderObject* oldChild)
{
// No need to waste time in merging or removing empty anonymous blocks.
// We can just bail out if our document is getting destroyed.
if (documentBeingDestroyed()) {
RenderBox::removeChild(oldChild);
return;
}
// If this child is a block, and if our previous and next siblings are
// both anonymous blocks with inline content, then we can go ahead and
// fold the inline content back together.
RenderObject* prev = oldChild->previousSibling();
RenderObject* next = oldChild->nextSibling();
bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
if (canMergeAnonymousBlocks && prev && next) {
prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
RenderBlockFlow* nextBlock = toRenderBlockFlow(next);
RenderBlockFlow* prevBlock = toRenderBlockFlow(prev);
if (prev->childrenInline() != next->childrenInline()) {
RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
// Place the inline children block inside of the block children block instead of deleting it.
// In order to reuse it, we have to reset it to just be a generic anonymous block. Make sure
// 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::createAnonymousStyleWithDisplay(style(), BLOCK);
// Cache this value as it might get changed in setStyle() call.
bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
inlineChildrenBlock->setStyle(newStyle);
children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer);
// Now just put the inlineChildrenBlock inside the blockChildrenBlock.
blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
// inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
// of "this". we null out prev or next so that is not used later in the function.
if (inlineChildrenBlock == prevBlock)
prev = 0;
else
next = 0;
} else {
// Take all the children out of the |next| block and put them in
// the |prev| block.
nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
// Delete the now-empty block's lines and nuke it.
nextBlock->deleteLineBoxTree();
nextBlock->destroy();
next = 0;
}
}
RenderBox::removeChild(oldChild);
RenderObject* child = prev ? prev : next;
if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
// The removal has knocked us down to containing only a single anonymous
// box. We can go ahead and pull the content right back up into our
// box.
collapseAnonymousBlockChild(this, toRenderBlock(child));
}
// No need to waste time deleting the line box tree if we're getting destroyed.
if (documentBeingDestroyed())
return;
if (!firstChild()) {
// If this was our last child be sure to clear out our line boxes.
if (childrenInline())
deleteLineBoxTree();
// If we are an empty anonymous block in the continuation chain,
// we need to remove ourself and fix the continuation chain.
if (!beingDestroyed() && isAnonymousBlockContinuation()) {
RenderObject* containingBlockIgnoringAnonymous = containingBlock();
while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymous())
containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
if (curr->virtualContinuation() != this)
continue;
// Found our previous continuation. We just need to point it to
// |this|'s next continuation.
RenderBoxModelObject* nextContinuation = continuation();
if (curr->isRenderInline())
toRenderInline(curr)->setContinuation(nextContinuation);
else if (curr->isRenderBlock())
toRenderBlock(curr)->setContinuation(nextContinuation);
else
ASSERT_NOT_REACHED();
break;
}
setContinuation(0);
destroy();
}
}
// If this was our last child be sure to clear out our line boxes.
if (!firstChild() && childrenInline())
deleteLineBoxTree();
}
void RenderBlock::startDelayUpdateScrollInfo()
@ -1078,17 +804,11 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
// 5. paint outline.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && style()->hasOutline()) {
// Don't paint focus ring for anonymous block continuation because the
// inline element having outline-style:auto paints the whole focus ring.
if (!style()->outlineStyleIsAuto() || !isAnonymousBlockContinuation())
paintOutline(paintInfo, LayoutRect(paintOffset, size()));
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline)
&& style()->hasOutline() && !style()->outlineStyleIsAuto()) {
paintOutline(paintInfo, LayoutRect(paintOffset, size()));
}
// 6. paint continuation outlines.
if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines))
paintContinuationOutlines(paintInfo, paintOffset);
// 7. paint caret.
// If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
// then paint the caret.
@ -1096,104 +816,6 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
paintCarets(paintInfo, paintOffset);
}
RenderInline* RenderBlock::inlineElementContinuation() const
{
RenderBoxModelObject* continuation = this->continuation();
return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
}
RenderBlock* RenderBlock::blockElementContinuation() const
{
RenderBoxModelObject* currentContinuation = continuation();
if (!currentContinuation || currentContinuation->isInline())
return 0;
RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
if (nextContinuation->isAnonymousBlock())
return nextContinuation->blockElementContinuation();
return nextContinuation;
}
static ContinuationOutlineTableMap* continuationOutlineTable()
{
DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
return &table;
}
void RenderBlock::addContinuationWithOutline(RenderInline* flow)
{
// We can't make this work if the inline is in a layer. We'll just rely on the broken
// way of painting.
ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
ContinuationOutlineTableMap* table = continuationOutlineTable();
ListHashSet<RenderInline*>* continuations = table->get(this);
if (!continuations) {
continuations = new ListHashSet<RenderInline*>;
table->set(this, adoptPtr(continuations));
}
continuations->add(flow);
}
bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
{
ContinuationOutlineTableMap* table = continuationOutlineTable();
if (table->isEmpty())
return false;
ListHashSet<RenderInline*>* continuations = table->get(this);
if (!continuations)
return false;
return continuations->contains(flow);
}
void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
{
RenderInline* inlineCont = inlineElementContinuation();
if (inlineCont && inlineCont->style()->hasOutline()) {
RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
RenderBlock* cb = containingBlock();
bool inlineEnclosedInSelfPaintingLayer = false;
for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
if (box->hasSelfPaintingLayer()) {
inlineEnclosedInSelfPaintingLayer = true;
break;
}
}
// 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), paint them straightaway instead. This is because a block depends on renderers in its continuation table being
// in the same layer.
if (!inlineEnclosedInSelfPaintingLayer && !hasLayer())
cb->addContinuationWithOutline(inlineRenderer);
else if (!inlineRenderer->firstLineBox() || (!inlineEnclosedInSelfPaintingLayer && hasLayer()))
inlineRenderer->paintOutline(info, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
}
ContinuationOutlineTableMap* table = continuationOutlineTable();
if (table->isEmpty())
return;
OwnPtr<ListHashSet<RenderInline*> > continuations = table->take(this);
if (!continuations)
return;
LayoutPoint accumulatedPaintOffset = paintOffset;
// Paint each continuation outline.
ListHashSet<RenderInline*>::iterator end = continuations->end();
for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
// Need to add in the coordinates of the intervening blocks.
RenderInline* flow = *it;
RenderBlock* block = flow->containingBlock();
for ( ; block && block != this; block = block->containingBlock())
accumulatedPaintOffset.moveBy(block->location());
ASSERT(block);
flow->paintOutline(info, accumulatedPaintOffset);
}
}
bool RenderBlock::shouldPaintSelectionGaps() const
{
return selectionState() != SelectionNone && isSelectionRoot();
@ -1743,14 +1365,6 @@ void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit l
}
}
Node* RenderBlock::nodeForHitTest() const
{
// If we are in the margins of block elements that are part of a
// continuation we're actually still inside the enclosing element
// that was split. Use the appropriate inner node.
return isAnonymousBlockContinuation() ? continuation()->node() : node();
}
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
LayoutPoint adjustedLocation(accumulatedOffset + location());
@ -1820,7 +1434,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
LayoutRect boundsRect(adjustedLocation, size());
if (visibleToHitTestRequest(request) && locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, locationInContainer.point() - localOffset);
if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer, boundsRect))
if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
return true;
}
}
@ -2390,49 +2004,12 @@ void RenderBlock::clearTruncation()
void RenderBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
// For blocks inside inlines, we go ahead and include margins so that we run right up to the
// inline boxes above and below us (thus getting merged with them to form a single irregular
// shape).
if (isAnonymousBlockContinuation()) {
// FIXME: This is wrong for block-flows that are horizontal.
// https://bugs.webkit.org/show_bug.cgi?id=46781
rects.append(pixelSnappedIntRect(accumulatedOffset.x(), accumulatedOffset.y() - marginBefore(),
width(), height() + marginBefore() + marginAfter()));
continuation()->absoluteRects(rects, accumulatedOffset - toLayoutSize(location() +
inlineElementContinuation()->containingBlock()->location()));
} else
rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
}
void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads) const
{
// For blocks inside inlines, we go ahead and include margins so that we run right up to the
// inline boxes above and below us (thus getting merged with them to form a single irregular
// shape).
if (isAnonymousBlockContinuation()) {
// FIXME: This is wrong for block-flows that are horizontal.
// https://bugs.webkit.org/show_bug.cgi?id=46781
FloatRect localRect(0, -marginBefore().toFloat(),
width().toFloat(), (height() + marginBefore() + marginAfter()).toFloat());
quads.append(localToAbsoluteQuad(localRect, 0 /* mode */));
continuation()->absoluteQuads(quads);
} else {
quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width().toFloat(), height().toFloat()), 0 /* mode */));
}
}
LayoutRect RenderBlock::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* paintInvalidationState) const
{
LayoutRect r(RenderBox::rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineWidth, paintInvalidationState));
if (isAnonymousBlockContinuation())
r.inflateY(marginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
return r;
}
void RenderBlock::childBecameNonInline(RenderObject*)
{
ASSERT_NOT_REACHED();
// FIXME(sky): Remove
quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width().toFloat(), height().toFloat()), 0 /* mode */));
}
void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
@ -2440,7 +2017,7 @@ void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint&
if (result.innerNode())
return;
if (Node* n = nodeForHitTest()) {
if (Node* n = node()) {
result.setInnerNode(n);
if (!result.innerNonSharedNode())
result.setInnerNonSharedNode(n);
@ -2464,24 +2041,8 @@ LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, La
void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer) const
{
// For blocks inside inlines, we go ahead and include margins so that we run right up to the
// inline boxes above and below us (thus getting merged with them to form a single irregular
// shape).
if (inlineElementContinuation()) {
// FIXME: This check really isn't accurate.
bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox();
// FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
// FIXME: This is wrong for block-flows that are horizontal.
// https://bugs.webkit.org/show_bug.cgi?id=46781
bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox();
LayoutUnit topMargin = prevInlineHasLineBox ? marginBefore() : LayoutUnit();
LayoutUnit bottomMargin = nextInlineHasLineBox ? marginAfter() : LayoutUnit();
LayoutRect rect(additionalOffset.x(), additionalOffset.y() - topMargin, width(), height() + topMargin + bottomMargin);
if (!rect.isEmpty())
rects.append(pixelSnappedIntRect(rect));
} else if (width() && height()) {
if (width() && height())
rects.append(pixelSnappedIntRect(additionalOffset, size()));
}
if (!hasOverflowClip() && !hasControlClip()) {
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
@ -2494,14 +2055,6 @@ void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& a
addChildFocusRingRects(rects, additionalOffset, paintContainer);
}
if (inlineElementContinuation())
inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location()), paintContainer);
}
RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const
{
return createAnonymousWithParentRendererAndDisplay(parent, style()->display());
}
LayoutUnit RenderBlock::marginBeforeForChild(const RenderBox* child) const

View File

@ -164,22 +164,9 @@ public:
int heightForLineCount(int);
void clearTruncation();
void addContinuationWithOutline(RenderInline*);
bool paintsContinuationOutline(RenderInline*);
virtual RenderBoxModelObject* virtualContinuation() const override final { return continuation(); }
bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); }
RenderInline* inlineElementContinuation() const;
RenderBlock* blockElementContinuation() const;
using RenderBoxModelObject::continuation;
using RenderBoxModelObject::setContinuation;
static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = PARAGRAPH);
RenderBlock* createAnonymousBlock(EDisplay display = PARAGRAPH) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override;
// Accessors for logical width/height and margins in the containing block's block-flow direction.
LayoutUnit logicalWidthForChild(const RenderBox* child) const { return child->width(); }
LayoutUnit logicalHeightForChild(const RenderBox* child) const { return child->height(); }
@ -303,16 +290,11 @@ private:
virtual void dirtyLinesFromChangedChild(RenderObject* child) override final { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild) override;
void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
Node* nodeForHitTest() const;
void paintContents(PaintInfo&, const LayoutPoint&);
void paintSelection(PaintInfo&, const LayoutPoint&);
void paintCarets(PaintInfo&, const LayoutPoint&);
@ -327,10 +309,6 @@ private:
// children.
virtual RenderBlock* firstLineBlock() const override;
virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* = 0) const override final;
virtual void childBecameNonInline(RenderObject* child) override final;
virtual LayoutRect selectionRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, bool /*clipToVisibleContent*/) override final
{
return selectionGapRectsForPaintInvalidation(paintInvalidationContainer);
@ -348,8 +326,6 @@ private:
virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override;
virtual void absoluteQuads(Vector<FloatQuad>&) const override;
void paintContinuationOutlines(PaintInfo&, const LayoutPoint&);
virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) override final;
void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
@ -357,11 +333,6 @@ private:
Position positionForBox(InlineBox*, bool start = true) const;
PositionWithAffinity positionForPointWithInlineChildren(const LayoutPoint&);
void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont);
RenderBlock* clone() const;
RenderBlock* continuationBefore(RenderObject* beforeChild);
// End helper functions and structs used by layoutBlockChildren.
void removeFromGlobalMaps();

View File

@ -223,8 +223,6 @@ RootInlineBox* RenderBlockFlow::constructLine(BidiRunList<BidiRun>& bidiRuns, co
}
}
// We should have a root inline box. It should be unconstructed and
// be the last continuation of our line list.
ASSERT(lastLineBox() && !lastLineBox()->isConstructed());
// Set the m_selectedChildren flag on the root inline box if one of the leaf inline box

View File

@ -485,12 +485,6 @@ public:
virtual bool hasRelativeLogicalHeight() const;
virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject*) const
{
ASSERT_NOT_REACHED();
return 0;
}
bool hasSameDirectionAs(const RenderBox* object) const { return style()->direction() == object->style()->direction(); }
protected:

View File

@ -46,16 +46,6 @@
namespace blink {
// The HashMap for storing continuation pointers.
// An inline can be split with blocks occuring in between the inline content.
// When this occurs we need a pointer to the next object. We can basically be
// split into a sequence of inlines and blocks. The continuation will either be
// an anonymous block (that houses other blocks) or it will be an inline flow.
// <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
// its continuation but the <b> will just have an inline as its continuation.
typedef HashMap<RawPtr<const RenderBoxModelObject>, RawPtr<RenderBoxModelObject> > ContinuationMap;
static OwnPtr<ContinuationMap>* continuationMap = 0;
void RenderBoxModelObject::setSelectionState(SelectionState state)
{
if (state == SelectionInside && selectionState() != SelectionNone)
@ -105,10 +95,6 @@ RenderBoxModelObject::~RenderBoxModelObject()
void RenderBoxModelObject::willBeDestroyed()
{
ImageQualityController::remove(this);
// A continuation of this RenderObject should be destroyed at subclasses.
ASSERT(!continuation());
RenderLayerModelObject::willBeDestroyed();
}
@ -129,22 +115,6 @@ void RenderBoxModelObject::updateFromStyle()
setPositionState(styleToUse->position());
}
static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child)
{
if (!child->isAnonymousBlock() || !child->isRelPositioned())
return LayoutSize();
LayoutSize offset;
RenderObject* p = toRenderBlock(child)->inlineElementContinuation();
while (p && p->isRenderInline()) {
if (p->isRelPositioned()) {
RenderInline* renderInline = toRenderInline(p);
offset += renderInline->offsetForInFlowPosition();
}
p = p->parent();
}
return offset;
}
bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
{
Length logicalHeightLength = style()->logicalHeight();
@ -219,7 +189,7 @@ void RenderBoxModelObject::paintRootBackgroundColor(const PaintInfo& paintInfo,
LayoutSize RenderBoxModelObject::relativePositionOffset() const
{
LayoutSize offset = accumulateInFlowPositionOffsets(this);
LayoutSize offset;
RenderBlock* containingBlock = this->containingBlock();
@ -2428,25 +2398,6 @@ LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
return containingBlock()->availableLogicalWidth();
}
RenderBoxModelObject* RenderBoxModelObject::continuation() const
{
if (!continuationMap)
return 0;
return (*continuationMap)->get(this);
}
void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation)
{
if (continuation) {
if (!continuationMap)
continuationMap = new OwnPtr<ContinuationMap>(adoptPtr(new ContinuationMap));
(*continuationMap)->set(this, continuation);
} else {
if (continuationMap)
(*continuationMap)->remove(this);
}
}
LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset)
{
ASSERT(!slowFirstChild());
@ -2590,7 +2541,7 @@ void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, R
toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
}
void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
void RenderBoxModelObject::moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert)
{
// This condition is rarely hit since this function is usually called on
// anonymous blocks which can no longer carry positioned objects (see r120761)
@ -2601,7 +2552,7 @@ void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject
}
ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
for (RenderObject* child = startChild; child && child != endChild; ) {
for (RenderObject* child = slowFirstChild(); child; ) {
// Save our next sibling as moveChildTo will clear it.
RenderObject* nextSibling = child->nextSibling();
moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);

View File

@ -151,8 +151,6 @@ public:
LayoutUnit containingBlockLogicalWidthForContent() const;
virtual void childBecameNonInline(RenderObject* /*child*/) { }
void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle*, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
bool paintNinePieceImage(GraphicsContext*, const LayoutRect&, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
@ -250,9 +248,6 @@ protected:
InterpolationQuality chooseInterpolationQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
RenderBoxModelObject* continuation() const;
virtual void setContinuation(RenderBoxModelObject*);
LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
static void clipRoundedInnerRect(GraphicsContext*, const LayoutRect&, const RoundedRect& clipRect);
@ -267,28 +262,8 @@ public:
static bool shouldAntialiasLines(GraphicsContext*);
// These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
// Since they are typically called only to move objects around within anonymous blocks (which only have layers in
// the case of column spans), the default for fullRemoveInsert is false rather than true.
void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, bool fullRemoveInsert = false)
{
moveChildTo(toBoxModelObject, child, 0, fullRemoveInsert);
}
void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, bool fullRemoveInsert = false)
{
moveAllChildrenTo(toBoxModelObject, 0, fullRemoveInsert);
}
void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert = false)
{
moveChildrenTo(toBoxModelObject, slowFirstChild(), 0, beforeChild, fullRemoveInsert);
}
// Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the |endChild| to denote
// that all the kids from |startChild| onwards should be moved.
void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
{
moveChildrenTo(toBoxModelObject, startChild, endChild, 0, fullRemoveInsert);
}
void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert);
void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert);
IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize) const;

View File

@ -63,32 +63,10 @@ RenderInline* RenderInline::createAnonymous(Document* document)
void RenderInline::willBeDestroyed()
{
#if ENABLE(ASSERT)
// Make sure we do not retain "this" in the continuation outline table map of our containing blocks.
if (parent() && style()->hasOutline()) {
bool containingBlockPaintsContinuationOutline = continuation() || isInlineElementContinuation();
if (containingBlockPaintsContinuationOutline) {
if (RenderBlock* cb = containingBlock()) {
if (RenderBlock* cbCb = cb->containingBlock())
ASSERT(!cbCb->paintsContinuationOutline(this));
}
}
}
#endif
// Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
// properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
children()->destroyLeftoverChildren();
// Destroy our continuation before anything other than anonymous children.
// The reason we don't destroy it before anonymous children is that they may
// have continuations of their own that are anonymous children of our continuation.
RenderBoxModelObject* continuation = this->continuation();
if (continuation) {
continuation->destroy();
setContinuation(0);
}
if (!documentBeingDestroyed()) {
if (firstLineBox()) {
// We can't wait for RenderBoxModelObject::destroy to clear the selection,
@ -116,14 +94,6 @@ void RenderInline::willBeDestroyed()
RenderBoxModelObject::willBeDestroyed();
}
RenderInline* RenderInline::inlineElementContinuation() const
{
RenderBoxModelObject* continuation = this->continuation();
if (!continuation || continuation->isInline())
return toRenderInline(continuation);
return toRenderBlock(continuation)->inlineElementContinuation();
}
void RenderInline::updateFromStyle()
{
RenderBoxModelObject::updateFromStyle();
@ -135,74 +105,12 @@ void RenderInline::updateFromStyle()
setHasTransform(false);
}
static RenderObject* inFlowPositionedInlineAncestor(RenderObject* p)
{
while (p && p->isRenderInline()) {
if (p->isRelPositioned())
return p;
p = p->parent();
}
return 0;
}
static void updateStyleOfAnonymousBlockContinuations(RenderObject* block, const RenderStyle* newStyle, const RenderStyle* oldStyle)
{
for (;block && block->isAnonymousBlock(); block = block->nextSibling()) {
if (!toRenderBlock(block)->isAnonymousBlockContinuation())
continue;
if (!block->style()->isOutlineEquivalent(newStyle)) {
RefPtr<RenderStyle> blockStyle = RenderStyle::clone(block->style());
blockStyle->setOutlineFromStyle(*newStyle);
block->setStyle(blockStyle);
}
if (block->style()->position() != newStyle->position()) {
// If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then
// their containing anonymous block should keep its in-flow positioning.
if (oldStyle->hasInFlowPosition()
&& inFlowPositionedInlineAncestor(toRenderBlock(block)->inlineElementContinuation()))
continue;
// FIXME: We should share blockStyle with the outline case, but it fails layout tests
// for dynamic position change of inlines containing block continuations. crbug.com/405222.
RefPtr<RenderStyle> blockStyle = RenderStyle::createAnonymousStyleWithDisplay(block->style(), BLOCK);
blockStyle->setPosition(newStyle->position());
block->setStyle(blockStyle);
}
}
}
void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBoxModelObject::styleDidChange(diff, oldStyle);
// Ensure that all of the split inlines pick up the new style. We
// only do this if we're an inline, since we don't want to propagate
// a block's style to the other inlines.
// e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
// and after the block share the same style, but the block doesn't
// need to pass its style on to anyone else.
RenderStyle* newStyle = style();
RenderInline* continuation = inlineElementContinuation();
for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
RenderBoxModelObject* nextCont = currCont->continuation();
currCont->setContinuation(0);
currCont->setStyle(newStyle);
currCont->setContinuation(nextCont);
}
// If an inline's in-flow positioning has changed then any descendant blocks will need to change their in-flow positioning accordingly.
// Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
if (continuation && oldStyle
&& (!newStyle->isOutlineEquivalent(oldStyle)
|| (newStyle->position() != oldStyle->position() && (newStyle->hasInFlowPosition() || oldStyle->hasInFlowPosition())))) {
// If any descendant blocks exist then they will be in the next anonymous block and its siblings.
RenderObject* block = containingBlock()->nextSibling();
if (block && block->isAnonymousBlock())
updateStyleOfAnonymousBlockContinuations(block, newStyle, oldStyle);
}
if (!alwaysCreateLineBoxes()) {
RenderStyle* newStyle = style();
bool alwaysCreateLineBoxesNew = hasSelfPaintingLayer() || hasBoxDecorationBackground() || newStyle->hasPadding() || newStyle->hasMargin() || newStyle->hasOutline();
if (oldStyle && alwaysCreateLineBoxesNew) {
dirtyLineBoxes(false);
@ -212,18 +120,6 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
}
}
void RenderInline::setContinuation(RenderBoxModelObject* continuation)
{
RenderBoxModelObject::setContinuation(continuation);
if (continuation && continuation->isAnonymousBlock() && !continuation->style()->isOutlineEquivalent(style())) {
// Push outline style to the block continuation.
RefPtr<RenderStyle> blockStyle = RenderStyle::clone(continuation->style());
blockStyle->setOutlineFromStyle(*style());
continuation->setStyle(blockStyle);
}
// FIXME: What if continuation is added when the inline has relative position? crbug.com/405222.
}
void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
{
// Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the
@ -282,250 +178,10 @@ LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* e
void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
if (continuation())
return addChildToContinuation(newChild, beforeChild);
return addChildIgnoringContinuation(newChild, beforeChild);
}
static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
{
if (renderer->isInline() && !renderer->isReplaced())
return toRenderInline(renderer)->continuation();
return toRenderBlock(renderer)->inlineElementContinuation();
}
RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
{
if (beforeChild && beforeChild->parent() == this)
return this;
RenderBoxModelObject* curr = nextContinuation(this);
RenderBoxModelObject* nextToLast = this;
RenderBoxModelObject* last = this;
while (curr) {
if (beforeChild && beforeChild->parent() == curr) {
if (curr->slowFirstChild() == beforeChild)
return last;
return curr;
}
nextToLast = last;
last = curr;
curr = nextContinuation(curr);
}
if (!beforeChild && !last->slowFirstChild())
return nextToLast;
return last;
}
void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
// We are placing a block inside an inline. We have to perform a split of this
// inline into continuations. This involves creating an anonymous block box to hold
// |newChild|. We then make that block box a continuation of this inline. We take all of
// the children after |beforeChild| and put them in a clone of this object.
RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
// If inside an inline affected by in-flow positioning the block needs to be affected by it too.
// Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
if (RenderObject* positionedAncestor = inFlowPositionedInlineAncestor(this))
newStyle->setPosition(positionedAncestor->style()->position());
RenderBlockFlow* newBox = RenderBlockFlow::createAnonymous(&document());
newBox->setStyle(newStyle.release());
RenderBoxModelObject* oldContinuation = continuation();
setContinuation(newBox);
splitFlow(beforeChild, newBox, newChild, oldContinuation);
return;
}
RenderBoxModelObject::addChild(newChild, beforeChild);
newChild->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
RenderInline* RenderInline::clone() const
{
RenderInline* cloneInline = new RenderInline(node());
cloneInline->setStyle(style());
return cloneInline;
}
void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont)
{
// Create a clone of this inline.
RenderInline* cloneInline = clone();
cloneInline->setContinuation(oldCont);
// Now take all of the children from beforeChild to the end and remove
// them from |this| and place them in the clone.
RenderObject* o = beforeChild;
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
cloneInline->addChildIgnoringContinuation(children()->removeChildNode(this, tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
// Hook |clone| up as the continuation of the middle block.
middleBlock->setContinuation(cloneInline);
// We have been reparented and are now under the fromBlock. We need
// to walk up our inline parent chain until we hit the containing block.
// Once we hit the containing block we're done.
RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
RenderBoxModelObject* currChild = this;
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
// There will eventually be a better approach to this problem that will let us nest to a much
// greater depth (see bugzilla bug 13430) but for now we have a limit. This *will* result in
// incorrect rendering, but the alternative is to hang forever.
unsigned splitDepth = 1;
const unsigned cMaxSplitDepth = 200;
while (curr && curr != fromBlock) {
ASSERT(curr->isRenderInline());
if (splitDepth < cMaxSplitDepth) {
// Create a new clone.
RenderInline* cloneChild = cloneInline;
cloneInline = toRenderInline(curr)->clone();
// Insert our child clone as the first child.
cloneInline->addChildIgnoringContinuation(cloneChild, 0);
// Hook the clone up as a continuation of |curr|.
RenderInline* inlineCurr = toRenderInline(curr);
oldCont = inlineCurr->continuation();
inlineCurr->setContinuation(cloneInline);
cloneInline->setContinuation(oldCont);
// Now we need to take all of the children starting from the first child
// *after* currChild and append them all to the clone.
o = currChild->nextSibling();
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
cloneInline->addChildIgnoringContinuation(inlineCurr->children()->removeChildNode(curr, tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
// Keep walking up the chain.
currChild = curr;
curr = toRenderBoxModelObject(curr->parent());
splitDepth++;
}
// Now we are at the block level. We need to put the clone into the toBlock.
toBlock->children()->appendChildNode(toBlock, cloneInline);
// Now take all the children after currChild and remove them from the fromBlock
// and put them in the toBlock.
o = currChild->nextSibling();
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
toBlock->children()->appendChildNode(toBlock, fromBlock->children()->removeChildNode(fromBlock, tmp));
}
}
void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
RenderObject* newChild, RenderBoxModelObject* oldCont)
{
RenderBlock* pre = 0;
RenderBlock* block = containingBlock();
// Delete our line boxes before we do the inline split into continuations.
block->deleteLineBoxTree();
bool madeNewBeforeBlock = false;
if (block->isAnonymousBlock()) {
// We can reuse this block and make it the preBlock of the next continuation.
pre = block;
pre->removePositionedObjects(0);
block = block->containingBlock();
} else {
// No anonymous block available for use. Make one.
pre = block->createAnonymousBlock();
madeNewBeforeBlock = true;
}
RenderBlock* post = toRenderBlock(pre->createAnonymousBoxWithSameTypeAs(block));
RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
if (madeNewBeforeBlock)
block->children()->insertChildNode(block, pre, boxFirst);
block->children()->insertChildNode(block, newBlockBox, boxFirst);
block->children()->insertChildNode(block, post, boxFirst);
block->setChildrenInline(false);
if (madeNewBeforeBlock) {
RenderObject* o = boxFirst;
while (o) {
RenderObject* no = o;
o = no->nextSibling();
pre->children()->appendChildNode(pre, block->children()->removeChildNode(block, no));
no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
}
splitInlines(pre, post, newBlockBox, beforeChild, oldCont);
// We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
// time in makeChildrenNonInline by just setting this explicitly up front.
newBlockBox->setChildrenInline(false);
newBlockBox->addChild(newChild);
// Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
// get deleted properly. Because objects moves from the pre block into the post block, we want to
// make new line boxes instead of leaving the old line boxes around.
pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
}
void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
RenderBoxModelObject* flow = continuationBefore(beforeChild);
ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() || beforeChild->parent()->isRenderInline());
RenderBoxModelObject* beforeChildParent = 0;
if (beforeChild)
beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
else {
RenderBoxModelObject* cont = nextContinuation(flow);
if (cont)
beforeChildParent = cont;
else
beforeChildParent = flow;
}
if (newChild->isFloatingOrOutOfFlowPositioned())
return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
// A continuation always consists of two potential candidates: an inline or an anonymous
// block box holding block children.
bool childInline = newChild->isInline();
bool bcpInline = beforeChildParent->isInline();
bool flowInline = flow->isInline();
if (flow == beforeChildParent)
return flow->addChildIgnoringContinuation(newChild, beforeChild);
else {
// The goal here is to match up if we can, so that we can coalesce and create the
// minimal # of continuations needed for the inline.
if (childInline == bcpInline || (beforeChild && beforeChild->isInline()))
return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
if (flowInline == childInline)
return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
}
}
void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
@ -619,14 +275,6 @@ void RenderInline::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accu
{
AbsoluteRectsGeneratorContext context(rects, accumulatedOffset);
generateLineBoxRects(context);
if (continuation()) {
if (continuation()->isBox()) {
RenderBox* box = toRenderBox(continuation());
continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box->locationOffset()));
} else
continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
}
}
@ -656,9 +304,6 @@ void RenderInline::absoluteQuads(Vector<FloatQuad>& quads) const
{
AbsoluteQuadsGeneratorContext context(this, quads);
generateLineBoxRects(context);
if (continuation())
continuation()->absoluteQuads(quads);
}
LayoutUnit RenderInline::offsetLeft() const
@ -786,6 +431,9 @@ bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestRes
PositionWithAffinity RenderInline::positionForPoint(const LayoutPoint& point)
{
// FIXME(sky): Now that we don't have continuations, can this whole function just be the following?
// return containingBlock()->positionForPoint(point);
// FIXME: Does not deal with relative positioned inlines (should it?)
RenderBlock* cb = containingBlock();
if (firstLineBox()) {
@ -795,15 +443,6 @@ PositionWithAffinity RenderInline::positionForPoint(const LayoutPoint& point)
}
// Translate the coords from the pre-anonymous block to the post-anonymous block.
LayoutPoint parentBlockPoint = cb->location() + point;
RenderBoxModelObject* c = continuation();
while (c) {
RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
if (c->isInline() || c->slowFirstChild())
return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
c = toRenderBlock(c)->inlineElementContinuation();
}
return RenderBoxModelObject::positionForPoint(point);
}
@ -971,7 +610,7 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
LayoutRect RenderInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const
{
if (!firstLineBoxIncludingCulling() && !continuation())
if (!firstLineBoxIncludingCulling())
return LayoutRect();
LayoutRect paintInvalidationRect(linesVisualOverflowBoundingBox());
@ -1009,9 +648,6 @@ LayoutRect RenderInline::clippedOverflowRectForPaintInvalidation(const RenderLay
if (!curr->isText())
paintInvalidationRect.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
}
if (continuation() && !continuation()->isInline() && continuation()->parent())
paintInvalidationRect.unite(continuation()->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize));
}
return paintInvalidationRect;
@ -1137,17 +773,6 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* paintInvali
o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, paintInvalidationState);
}
void RenderInline::childBecameNonInline(RenderObject* child)
{
// We have to split the parent flow.
RenderBlock* newBox = containingBlock()->createAnonymousBlock();
RenderBoxModelObject* oldContinuation = continuation();
setContinuation(newBox);
RenderObject* beforeChild = child->nextSibling();
children()->removeChildNode(this, child);
splitFlow(beforeChild, newBox, child, oldContinuation);
}
void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
{
if (result.innerNode())
@ -1156,16 +781,6 @@ void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint&
Node* n = node();
LayoutPoint localPoint(point);
if (n) {
if (isInlineElementContinuation()) {
// We're in the continuation of a split inline. Adjust our local point to be in the coordinate space
// of the principal renderer's containing block. This will end up being the innerNonSharedNode.
RenderBlock* firstBlock = n->renderer()->containingBlock();
// Get our containing block.
RenderBox* block = containingBlock();
localPoint.moveBy(block->location() - firstBlock->locationOffset());
}
result.setInnerNode(n);
if (!result.innerNonSharedNode())
result.setInnerNonSharedNode(n);
@ -1310,16 +925,6 @@ void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&
generateLineBoxRects(context);
addChildFocusRingRects(rects, additionalOffset, paintContainer);
if (continuation()) {
// If the continuation doesn't paint into the same container, let its paint invalidation container handle it.
if (paintContainer != continuation()->containerForPaintInvalidation())
return;
if (continuation()->isInline())
continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + continuation()->containingBlock()->location() - containingBlock()->location()), paintContainer);
else
continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + toRenderBox(continuation())->location() - containingBlock()->location()), paintContainer);
}
}
namespace {

View File

@ -77,17 +77,11 @@ public:
InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); }
InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); }
virtual RenderBoxModelObject* virtualContinuation() const override final { return continuation(); }
RenderInline* inlineElementContinuation() const;
LayoutSize offsetForInFlowPositionedInline(const RenderBox& child) const;
virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) const override final;
void paintOutline(PaintInfo&, const LayoutPoint&);
using RenderBoxModelObject::continuation;
virtual void setContinuation(RenderBoxModelObject*) override final;
bool alwaysCreateLineBoxes() const { return alwaysCreateLineBoxesForRenderInline(); }
void setAlwaysCreateLineBoxes(bool alwaysCreateLineBoxes = true) { setAlwaysCreateLineBoxesForRenderInline(alwaysCreateLineBoxes); }
void updateAlwaysCreateLineBoxes(bool fullLayout);
@ -120,14 +114,6 @@ private:
template<typename GeneratorContext>
void generateCulledLineBoxRects(GeneratorContext& yield, const RenderInline* container) const;
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) override final;
void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
RenderObject* beforeChild, RenderBoxModelObject* oldCont);
void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
RenderObject* newChild, RenderBoxModelObject* oldCont);
virtual void layout() override final { ASSERT_NOT_REACHED(); } // Do nothing for layout()
virtual void paint(PaintInfo&, const LayoutPoint&) override final;
@ -162,19 +148,14 @@ private:
virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override final;
virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override final;
virtual void childBecameNonInline(RenderObject* child) override final;
virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) override final;
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) override final;
virtual void updateFromStyle() override final;
RenderInline* clone() const;
void paintOutlineForLine(GraphicsContext*, const LayoutPoint&, const LayoutRect& prevLine, const LayoutRect& thisLine,
const LayoutRect& nextLine, const Color);
RenderBoxModelObject* continuationBefore(RenderObject* beforeChild);
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes; // All of the line boxes created for this inline flow. For example, <i>Hello<br>world.</i> will have two <i> line boxes.

View File

@ -1857,14 +1857,7 @@ void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
continue;
RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), child->style()->display());
// Preserve the position style of anonymous block continuations as they can have relative position when
// they contain block descendants of relative positioned inlines.
if (child->isRelPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
newStyle->setPosition(child->style()->position());
updateAnonymousChildStyle(child, newStyle.get());
child->setStyle(newStyle.release());
}
}
@ -2211,9 +2204,6 @@ void RenderObject::destroyAndCleanupAnonymousWrappers()
RenderObject* destroyRoot = this;
for (RenderObject* destroyRootParent = destroyRoot->parent(); destroyRootParent && destroyRootParent->isAnonymous(); destroyRoot = destroyRootParent, destroyRootParent = destroyRootParent->parent()) {
// Anonymous block continuations are tracked and destroyed elsewhere (see the bottom of RenderBlock::removeChild)
if (destroyRootParent->isRenderBlock() && toRenderBlock(destroyRootParent)->isAnonymousBlockContinuation())
break;
if (destroyRootParent->slowFirstChild() != this || destroyRootParent->slowLastChild() != this)
break;
}
@ -2373,8 +2363,6 @@ void RenderObject::getTextDecorations(unsigned decorations, AppliedTextDecoratio
}
}
curr = curr->parent();
if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuation())
curr = toRenderBlock(curr)->continuation();
} while (curr && decorations && (!quirksMode || !curr->node() || (!isHTMLAnchorElement(*curr->node()))));
// If we bailed out, use the element we bailed out at (typically a <font> or <a> element).

View File

@ -274,7 +274,6 @@ public:
virtual bool canHaveChildren() const { return virtualChildren(); }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; }
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); }
virtual void removeChild(RenderObject*);
//////////////////////////////////////////
@ -379,10 +378,6 @@ public:
return isAnonymous() && style()->display() == PARAGRAPH;
}
bool isElementContinuation() const { return node() && node()->renderer() != this; }
bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); }
virtual RenderBoxModelObject* virtualContinuation() const { return 0; }
bool isOutOfFlowPositioned() const { return m_bitfields.isOutOfFlowPositioned(); } // absolute or fixed positioning
bool isRelPositioned() const { return m_bitfields.isRelPositioned(); } // relative positioning
bool isPositioned() const { return m_bitfields.isPositioned(); }

View File

@ -914,18 +914,6 @@ public:
void setOutlineStyleIsAuto(OutlineIsAuto isAuto) { SET_VAR(m_background, m_outline.m_isAuto, isAuto); }
void setOutlineStyle(EBorderStyle v) { SET_VAR(m_background, m_outline.m_style, v); }
void setOutlineColor(const StyleColor& v) { SET_BORDERVALUE_COLOR(m_background, m_outline, v); }
bool isOutlineEquivalent(const RenderStyle* otherStyle) const
{
// No other style, so we don't have an outline then we consider them to be the same.
if (!otherStyle)
return !hasOutline();
return m_background->outline().visuallyEqual(otherStyle->m_background->outline());
}
void setOutlineFromStyle(const RenderStyle& o)
{
ASSERT(!isOutlineEquivalent(&o));
m_background.access()->m_outline = o.m_background->m_outline;
}
void setOverflowX(EOverflow v) { noninherited_flags.overflowX = v; }
void setOverflowY(EOverflow v) { noninherited_flags.overflowY = v; }