void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) { if (toBase->childrenInline()) { // First check whether we move only wrapped inline objects. if (hasOnlyWrappedInlineChildren(fromBeforeChild)) { // The reason why the base is in block flow must be after beforeChild. // We therefore can extract the inline objects and move them to toBase. for (RenderObject* child = firstChild(); child != fromBeforeChild; child = firstChild()) { if (child->isAnonymousBlock()) { RenderBlock* anonBlock = toRenderBlock(child); ASSERT(anonBlock->childrenInline()); ASSERT(!anonBlock->inlineElementContinuation()); anonBlock->moveAllChildrenTo(toBase, toBase->children()); anonBlock->deleteLineBoxTree(); anonBlock->destroy(); } else { ASSERT(child->isFloatingOrPositioned()); moveChildTo(toBase, child); } } } else { // Moving block children -> have to set toBase as block flow toBase->makeChildrenNonInline(); // Move children, potentially collapsing anonymous block wrappers. mergeBlockChildren(toBase, fromBeforeChild); // Now we need to check if the leftover children are all inline. // If so, make this base inline again. if (hasOnlyWrappedInlineChildren()) { RenderObject* next = 0; for (RenderObject* child = firstChild(); child; child = next) { next = child->nextSibling(); if (child->isFloatingOrPositioned()) continue; ASSERT(child->isAnonymousBlock()); RenderBlock* anonBlock = toRenderBlock(child); ASSERT(anonBlock->childrenInline()); ASSERT(!anonBlock->inlineElementContinuation()); // Move inline children out of anonymous block. anonBlock->moveAllChildrenTo(this, anonBlock); anonBlock->deleteLineBoxTree(); anonBlock->destroy(); } setChildrenInline(true); } } } else mergeBlockChildren(toBase, fromBeforeChild); }
void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild) { ASSERT(!childrenInline()); ASSERT_ARG(toBase, toBase); if (!firstChild()) return; if (toBase->childrenInline()) toBase->makeChildrenNonInline(); // If an anonymous block would be put next to another such block, then merge those. RenderObject* firstChildHere = firstChild(); RenderObject* lastChildThere = toBase->lastChild(); if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); anonBlockHere->moveAllChildrenTo(anonBlockThere, true); anonBlockHere->deleteLineBoxTree(); anonBlockHere->destroy(); } // Move all remaining children normally. moveChildrenTo(toBase, firstChild(), beforeChild); }
void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) { // This function removes all children that are before fromBeforeChild and appends them to toBase. ASSERT(!childrenInline()); ASSERT(toBase); ASSERT(!toBase->childrenInline()); // Quick check whether we have anything to do, to simplify the following code. if (fromBeforeChild != firstChild()) return; // If an anonymous block would be put next to another such block, then merge those. RenderObject* firstChildHere = firstChild(); RenderObject* lastChildThere = toBase->lastChild(); if (firstChildHere && firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children()); anonBlockHere->deleteLineBoxTree(); anonBlockHere->destroy(); } // Move all remaining children normally. moveChildrenTo(toBase, firstChild(), fromBeforeChild); }
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(); } } }