void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild, RenderFlow* 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() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) { // We can reuse this block and make it the preBlock of the next continuation. pre = block; block = block->containingBlock(); } else { // No anonymous block available for use. Make one. pre = block->createAnonymousBlock(); madeNewBeforeBlock = true; } RenderBlock* post = block->createAnonymousBlock(); RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling(); if (madeNewBeforeBlock) block->insertChildNode(pre, boxFirst); block->insertChildNode(newBlockBox, boxFirst); block->insertChildNode(post, boxFirst); block->setChildrenInline(false); if (madeNewBeforeBlock) { RenderObject* o = boxFirst; while (o) { RenderObject* no = o; o = no->nextSibling(); pre->appendChildNode(block->removeChildNode(no)); no->setNeedsLayoutAndPrefWidthsRecalc(); } } 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); // We don't just call addChild, since it would pass things off to the // continuation, so we call addChildToFlow explicitly instead. We delayed // adding the newChild until now so that the |newBlockBox| would be fully // connected, thus allowing newChild access to a renderArena should it need // to wrap itself in additional boxes (e.g., table construction). newBlockBox->addChildToFlow(newChild, 0); // 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->setNeedsLayoutAndPrefWidthsRecalc(); block->setNeedsLayoutAndPrefWidthsRecalc(); post->setNeedsLayoutAndPrefWidthsRecalc(); }
RenderObject* RenderRubyRun::removeChild(RenderObject& child) { // If the child is a ruby text, then merge the ruby base with the base of // the right sibling run, if possible. if (!beingDestroyed() && !documentBeingDestroyed() && child.isRubyText()) { RenderRubyBase* base = rubyBase(); RenderObject* rightNeighbour = nextSibling(); if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. RenderRubyRun* rightRun = toRenderRubyRun(rightNeighbour); if (rightRun->hasRubyBase()) { RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); // Collect all children in a single base, then swap the bases. rightBase->mergeChildrenWithBase(base); moveChildTo(rightRun, base); rightRun->moveChildTo(this, rightBase); // The now empty ruby base will be removed below. ASSERT(!rubyBase()->firstChild()); } } } RenderObject* next = RenderBlockFlow::removeChild(child); if (!beingDestroyed() && !documentBeingDestroyed()) { // Check if our base (if any) is now empty. If so, destroy it. RenderBlock* base = rubyBase(); if (base && !base->firstChild()) { next = RenderBlockFlow::removeChild(*base); base->deleteLines(); base->destroy(); } // If any of the above leaves the run empty, destroy it as well. if (isEmpty()) { parent()->removeChild(*this); deleteLines(); destroy(); next = nullptr; } } return next; }
void RenderRubyRun::removeChild(RenderObject* child) { // If the child is a ruby text, then merge the ruby base with the base of // the right sibling run, if possible. if (!m_beingDestroyed && !documentBeingDestroyed() && child->isRubyText()) { RenderRubyBase* base = rubyBase(); RenderObject* rightNeighbour = nextSibling(); if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. RenderRubyRun* rightRun = static_cast<RenderRubyRun*>(rightNeighbour); if (rightRun->hasRubyBase()) { RenderRubyBase* rightBase = rightRun->rubyBaseSafe(); // Collect all children in a single base, then swap the bases. rightBase->moveChildren(base); moveChildTo(rightRun, base); rightRun->moveChildTo(this, rightBase); // The now empty ruby base will be removed below. } } } RenderBlock::removeChild(child); if (!m_beingDestroyed && !documentBeingDestroyed()) { // Check if our base (if any) is now empty. If so, destroy it. RenderBlock* base = rubyBase(); if (base && !base->firstChild()) { RenderBlock::removeChild(base); base->deleteLineBoxTree(); base->destroy(); } // If any of the above leaves the run empty, destroy it as well. if (isEmpty()) { parent()->removeChild(this); deleteLineBoxTree(); destroy(); } } }
void RenderInline::splitFlow(RenderObject *beforeChild, RenderBlock *newBlockBox, RenderObject *newChild, RenderFlow *oldCont) { RenderBlock *pre = 0; RenderBlock *block = containingBlock(); bool madeNewBeforeBlock = false; if(block->isAnonymousBlock()) { // We can reuse this block and make it the preBlock of the next continuation. pre = block; block = block->containingBlock(); } else { // No anonymous block available for use. Make one. pre = block->createAnonymousBlock(); madeNewBeforeBlock = true; } RenderBlock *post = block->createAnonymousBlock(); RenderObject *boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling(); if(madeNewBeforeBlock) block->insertChildNode(pre, boxFirst); block->insertChildNode(newBlockBox, boxFirst); block->insertChildNode(post, boxFirst); block->setChildrenInline(false); if(madeNewBeforeBlock) { RenderObject *o = boxFirst; while(o) { RenderObject *no = o; o = no->nextSibling(); pre->appendChildNode(block->removeChildNode(no)); no->setNeedsLayoutAndMinMaxRecalc(); } } 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); // We don't just call addChild, since it would pass things off to the // continuation, so we call addChildToFlow explicitly instead. We delayed // adding the newChild until now so that the |newBlockBox| would be fully // connected, thus allowing newChild access to a renderArena should it need // to wrap itself in additional boxes (e.g., table construction). newBlockBox->addChildToFlow(newChild, 0); // XXXdwh is any of this even necessary? I don't think it is. pre->close(); pre->setPos(0, -500000); pre->setNeedsLayout(true); newBlockBox->close(); newBlockBox->setPos(0, -500000); newBlockBox->setNeedsLayout(true); post->close(); post->setPos(0, -500000); post->setNeedsLayout(true); updatePseudoChildren(); block->setNeedsLayoutAndMinMaxRecalc(); }