Exemple #1
0
RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby)
{
    ASSERT(parentRuby && parentRuby->isRuby());
    RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun(parentRuby->document() /* anonymous */);
    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentRuby->style(), INLINE_BLOCK);
    rr->setStyle(newStyle.release());
    return rr;
}
Exemple #2
0
void RenderRubyAsBlock::removeChild(RenderObject* child)
{
    // If the child's parent is *this (a ruby run or :before or :after content),
    // just use the normal remove method.
    if (child->isRubyRun() || child->isBeforeContent() || child->isAfterContent()) {
        RenderBlock::removeChild(child);
        return;
    }

    // Otherwise find the containing run and remove it from there.
    ASSERT(child->parent() != this);
    RenderRubyRun* run = findRubyRunParent(child);
    ASSERT(run);
    run->removeChild(child);
}
Exemple #3
0
void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
{
    ASSERT(child);

    if (child->isRubyText()) {
        if (!beforeChild) {
            // RenderRuby has already ascertained that we can add the child here.
            ASSERT(!hasRubyText());
            // prepend ruby texts as first child
            RenderBlockFlow::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);
            RenderObject* ruby = parent();
            ASSERT(ruby->isRuby());
            RenderBlock* 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 RenderRubyRun's methods,
            // in order to avoid automatic removal of the ruby run in case there is no
            // other child besides the old ruby text.
            RenderBlockFlow::addChild(child, beforeChild);
            RenderBlockFlow::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.
            RenderObject* ruby = parent();
            RenderRubyRun* newRun = staticCreateRubyRun(ruby);
            ruby->addChild(newRun, this);
            newRun->addChild(child);
            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)
        RenderRubyBase* base = rubyBaseSafe();
        if (beforeChild == base)
            beforeChild = base->firstChild();
        if (beforeChild && beforeChild->isRubyText())
            beforeChild = 0;
        ASSERT(!beforeChild || beforeChild->isDescendantOf(base));
        base->addChild(child, beforeChild);
    }
}
Exemple #4
0
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();
        }
    }
}
Exemple #6
0
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Insert :before and :after content outside of ruby runs.
    if (child->isBeforeContent() || child->isAfterContent()) {
        RenderInline::addChild(child, beforeChild);
        return;
    }

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

    if (beforeChild && !isAfterContent(beforeChild)) {
        // insert child into run
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (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 RenderRubyRun object will handle the details)
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderInline::addChild(lastRun);
    }
    lastRun->addChild(child);
}
Exemple #7
0
void RenderRubyAsBlock::removeChild(RenderObject* child)
{
    // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
    // just use the normal remove method.
    if (child->parent() == this) {
        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
        RenderBlock::removeChild(child);
        return;
    }
    // If the child's parent is an anoymous block (must be generated :before/:after content)
    // just use the block's remove method.
    if (isAnonymousRubyInlineBlock(child->parent())) {
        ASSERT(child->isBeforeContent() || child->isAfterContent());
        child->parent()->removeChild(child);
        removeChild(child->parent());
        return;
    }

    // Otherwise find the containing run and remove it from there.
    RenderRubyRun* run = findRubyRunParent(child);
    ASSERT(run);
    run->removeChild(child);
}
Exemple #8
0
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Insert :before and :after content before/after the RenderRubyRun(s)
    if (child->isBeforeContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderBlock::addChild(child, firstChild());
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* beforeBlock = rubyBeforeBlock(this);
            if (!beforeBlock) {
                beforeBlock = createAnonymousRubyInlineBlock(this);
                RenderBlock::addChild(beforeBlock, firstChild());
            }
            beforeBlock->addChild(child);
        }
        return;
    }
    if (child->isAfterContent()) {
        if (child->isInline()) {
            // Add generated inline content normally
            RenderBlock::addChild(child);
        } else {
            // Wrap non-inline content with an anonymous inline-block.
            RenderBlock* afterBlock = rubyAfterBlock(this);
            if (!afterBlock) {
                afterBlock = createAnonymousRubyInlineBlock(this);
                RenderBlock::addChild(afterBlock);
            }
            afterBlock->addChild(child);
        }
        return;
    }

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

    if (beforeChild && !isAfterContent(beforeChild)) {
        // insert child into run
        ASSERT(!beforeChild->isRubyRun());
        RenderObject* run = beforeChild;
        while (run && !run->isRubyRun())
            run = run->parent();
        if (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 RenderRubyRun object will handle the details)
    RenderRubyRun* lastRun = lastRubyRun(this);
    if (!lastRun || lastRun->hasRubyText()) {
        lastRun = RenderRubyRun::staticCreateRubyRun(this);
        RenderBlock::addChild(lastRun, beforeChild);
    }
    lastRun->addChild(child);
}