LayoutMultiColumnSet* LayoutMultiColumnSet::nextSiblingMultiColumnSet() const
{
    for (LayoutObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
        if (sibling->isLayoutMultiColumnSet())
            return toLayoutMultiColumnSet(sibling);
    }
    return nullptr;
}
LayoutMultiColumnSet* LayoutMultiColumnFlowThread::lastMultiColumnSet() const
{
    for (LayoutObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; sibling = sibling->previousSibling()) {
        if (sibling->isLayoutMultiColumnSet())
            return toLayoutMultiColumnSet(sibling);
    }
    return nullptr;
}
// When processing layout objects to remove or when processing layout objects that have just been
// inserted, certain types of objects should be skipped.
static bool shouldSkipInsertedOrRemovedChild(LayoutMultiColumnFlowThread* flowThread, const LayoutObject& child)
{
    if (child.isSVG() && !child.isSVGRoot()) {
        // Don't descend into SVG objects. What's in there is of no interest, and there might even
        // be a foreignObject there with column-span:all, which doesn't apply to us.
        return true;
    }
    if (child.isLayoutFlowThread()) {
        // Found an inner flow thread. We need to skip it and its descendants.
        return true;
    }
    if (child.isLayoutMultiColumnSet() || child.isLayoutMultiColumnSpannerPlaceholder()) {
        // Column sets and spanner placeholders in a child multicol context don't affect the parent
        // flow thread.
        return true;
    }
    if (child.isOutOfFlowPositioned() && child.containingBlock()->flowThreadContainingBlock() != flowThread) {
        // Out-of-flow with its containing block on the outside of the multicol container.
        return true;
    }
    return false;
}