Ejemplo n.º 1
0
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);
}
static bool isValidColumnSpanner(RenderMultiColumnFlowThread* flowThread, RenderObject* descendant)
{
    // We assume that we're inside the flow thread. This function is not to be called otherwise.
    ASSERT(descendant->isDescendantOf(flowThread));

    // First make sure that the renderer itself has the right properties for becoming a spanner.
    RenderStyle& style = descendant->style();
    if (style.columnSpan() != ColumnSpanAll || !descendant->isBox() || descendant->isFloatingOrOutOfFlowPositioned())
        return false;

    RenderBlock* container = descendant->containingBlock();
    if (!container->isRenderBlockFlow() || container->childrenInline()) {
        // Needs to be block-level.
        return false;
    }

    // This looks like a spanner, but if we're inside something unbreakable, it's not to be treated as one.
    for (RenderBox* ancestor = toRenderBox(descendant)->parentBox(); ancestor; ancestor = ancestor->parentBox()) {
        if (ancestor->isRenderFlowThread()) {
            // Don't allow any intervening non-multicol fragmentation contexts. The spec doesn't say
            // anything about disallowing this, but it's just going to be too complicated to
            // implement (not to mention specify behavior).
            return ancestor == flowThread;
        }
        ASSERT(ancestor->style().columnSpan() != ColumnSpanAll || !isValidColumnSpanner(flowThread, ancestor));
        if (ancestor->isUnsplittableForPagination())
            return false;
    }
    ASSERT_NOT_REACHED();
    return false;
}