void LayoutRubyRun::removeChild(LayoutObject* 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()) { LayoutRubyBase* base = rubyBase(); LayoutObject* rightNeighbour = nextSibling(); if (base && rightNeighbour && rightNeighbour->isRubyRun()) { // Ruby run without a base can happen only at the first run. LayoutRubyRun* rightRun = toLayoutRubyRun(rightNeighbour); if (rightRun->hasRubyBase()) { LayoutRubyBase* 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. ASSERT(!rubyBase()->firstChild()); } } } LayoutBlockFlow::removeChild(child); if (!beingDestroyed() && !documentBeingDestroyed()) { // Check if our base (if any) is now empty. If so, destroy it. LayoutBlock* base = rubyBase(); if (base && !base->firstChild()) { LayoutBlockFlow::removeChild(base); base->deleteLineBoxTree(); base->destroy(); } // If any of the above leaves the run empty, destroy it as well. if (!hasRubyText() && !hasRubyBase()) { deleteLineBoxTree(); destroy(); } } }
// We need to balance the benefit of subtree optimization and the cost of subtree display items. // Only output subtree information if the block has multiple children or multiple line boxes. static bool needsSubtreeRecorder(const LayoutBlock& layoutBlock) { return (layoutBlock.firstChild() && layoutBlock.firstChild()->nextSibling()) || (layoutBlock.isLayoutBlockFlow() && toLayoutBlockFlow(layoutBlock).firstLineBox() && toLayoutBlockFlow(layoutBlock).firstLineBox()->nextLineBox()); }