void LayoutRubyBase::moveBlockChildren(LayoutRubyBase* toBase, LayoutObject* 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. LayoutObject* firstChildHere = firstChild(); LayoutObject* lastChildThere = toBase->lastChild(); if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { LayoutBlock* anonBlockHere = toLayoutBlock(firstChildHere); LayoutBlock* anonBlockThere = toLayoutBlock(lastChildThere); anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children()); anonBlockHere->deleteLineBoxTree(); anonBlockHere->destroy(); } // Move all remaining children normally. moveChildrenTo(toBase, firstChild(), beforeChild); }
void LayoutRubyBase::moveInlineChildren(LayoutRubyBase* toBase, LayoutObject* beforeChild) { ASSERT(childrenInline()); ASSERT_ARG(toBase, toBase); if (!firstChild()) return; LayoutBlock* toBlock; if (toBase->childrenInline()) { // The standard and easy case: move the children into the target base toBlock = toBase; } else { // We need to wrap the inline objects into an anonymous block. // If toBase has a suitable block, we re-use it, otherwise create a new one. LayoutObject* lastChild = toBase->lastChild(); if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) { toBlock = toLayoutBlock(lastChild); } else { toBlock = toBase->createAnonymousBlock(); toBase->children()->appendChildNode(toBase, toBlock); } } // Move our inline children into the target block we determined above. moveChildrenTo(toBlock, firstChild(), beforeChild); }
bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, const LayoutObject& parent) { if (!parent.canHaveChildren()) return false; if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (!containsOnlyWhitespace()) return true; if (!canHaveWhitespaceChildren(parent, this)) return false; // pre-wrap in SVG never makes layoutObject. if (style.whiteSpace() == PRE_WRAP && parent.isSVG()) return false; // pre/pre-wrap/-bb-pre-wrap-text/pre-line always make layoutObjects. if (style.preserveNewline()) return true; // childNeedsDistributionRecalc() here is rare, only happens JS calling surroundContents() etc. from DOMNodeInsertedIntoDocument etc. if (document().childNeedsDistributionRecalc()) return true; const LayoutObject* prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (parent.isLayoutInline()) { // <span><div/> <div/></span> if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) return false; } else { if (parent.isLayoutBlock() && !parent.childrenInline() && (!prev || !prev->isInline())) return false; // Avoiding creation of a layoutObject for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; LayoutObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first || first == layoutObject() || LayoutTreeBuilderTraversal::nextSiblingLayoutObject(*this) == first) { // Whitespace at the start of a block just goes away. Don't even // make a layout object for this text. return false; } } return true; }