void LayoutRubyAsInline::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    // If the child is a ruby run, just add it normally.
    if (child->isRubyRun()) {
        LayoutInline::addChild(child, beforeChild);
        return;
    }

    if (beforeChild) {
        // insert child into run
        LayoutObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (run) {
            if (beforeChild == run)
                beforeChild = toLayoutRubyRun(beforeChild)->firstChild();
            ASSERT(!beforeChild || beforeChild->isDescendantOf(run));
            run->addChild(child, beforeChild);
            return;
        }
        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
        // Emergency fallback: fall through and just append.
    }

    // If the new child would be appended, try to add the child to the previous run
    // if possible, or create a new run otherwise.
    // (The LayoutRubyRun object will handle the details)
    LayoutRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = LayoutRubyRun::staticCreateRubyRun(this);
        LayoutInline::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}
Exemplo n.º 2
0
void LayoutRubyRun::addChild(LayoutObject* child, LayoutObject* beforeChild)
{
    ASSERT(child);

    if (child->isRubyText()) {
        if (!beforeChild) {
            // LayoutRuby has already ascertained that we can add the child here.
            ASSERT(!hasRubyText());
            // prepend ruby texts as first child
            LayoutBlockFlow::addChild(child, firstChild());
        }  else if (beforeChild->isRubyText()) {
            // New text is inserted just before another.
            // In this case the new text takes the place of the old one, and
            // the old text goes into a new run that is inserted as next sibling.
            ASSERT(beforeChild->parent() == this);
            LayoutObject* ruby = parent();
            ASSERT(ruby->isRuby());
            LayoutBlock* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, nextSibling());
            // Add the new ruby text and move the old one to the new run
            // Note: Doing it in this order and not using LayoutRubyRun's methods,
            // in order to avoid automatic removal of the ruby run in case there is no
            // other child besides the old ruby text.
            LayoutBlockFlow::addChild(child, beforeChild);
            LayoutBlockFlow::removeChild(beforeChild);
            newRun->addChild(beforeChild);
        } else if (hasRubyBase()) {
            // Insertion before a ruby base object.
            // In this case we need insert a new run before the current one and split the base.
            LayoutObject* ruby = parent();
            LayoutRubyRun* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, this);
            newRun->addChild(child);

            // Make sure we don't leave anything in the percentage descendant
            // map before moving the children to the new base.
            if (hasPercentHeightDescendants())
                clearPercentHeightDescendants();
            rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild);
        }
    } else {
        // child is not a text -> insert it into the base
        // (append it instead if beforeChild is the ruby text)
        LayoutRubyBase* base = rubyBaseSafe();
        if (beforeChild == base)
            beforeChild = base->firstChild();
        if (beforeChild && beforeChild->isRubyText())
            beforeChild = 0;
        ASSERT(!beforeChild || beforeChild->isDescendantOf(base));
        base->addChild(child, beforeChild);
    }
}