void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope)
{
    // Since we ended up here, it means that the multicol container (our parent) needed
    // layout. Since contents of the multicol container are diverted to the flow thread, the flow
    // thread needs layout as well.
    layoutScope.setChildNeedsLayout(this);

    m_blockOffsetInEnclosingFragmentationContext = enclosingFragmentationContext() ? multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage() : LayoutUnit();

    for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = columnBox->nextSiblingMultiColumnBox()) {
        if (!columnBox->isLayoutMultiColumnSet()) {
            ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no other type is expected.
            continue;
        }
        LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox);
        layoutScope.setChildNeedsLayout(columnSet);
        if (!m_columnHeightsChanged) {
            // This is the initial layout pass. We need to reset the column height, because contents
            // typically have changed.
            columnSet->resetColumnHeight();
        }
        // Since column sets are regular block flow objects, and their position is changed in
        // regular block layout code (with no means for the multicol code to notice unless we add
        // hooks there), store the previous position now. If it changes in the imminent layout
        // pass, we may have to rebalance its columns.
        columnSet->storeOldPosition();
    }

    m_columnHeightsChanged = false;
    invalidateColumnSets();
    layout();
    validateColumnSets();
}
LayoutMultiColumnSet* LayoutMultiColumnFlowThread::mapDescendantToColumnSet(LayoutObject* layoutObject) const
{
    ASSERT(!containingColumnSpannerPlaceholder(layoutObject)); // should not be used for spanners or content inside them.
    ASSERT(layoutObject != this);
    ASSERT(layoutObject->isDescendantOf(this));
    ASSERT(layoutObject->containingBlock()->isDescendantOf(this)); // Out-of-flow objects don't belong in column sets.
    ASSERT(layoutObject->flowThreadContainingBlock() == this);
    ASSERT(!layoutObject->isLayoutMultiColumnSet());
    ASSERT(!layoutObject->isLayoutMultiColumnSpannerPlaceholder());
    LayoutMultiColumnSet* multicolSet = firstMultiColumnSet();
    if (!multicolSet)
        return nullptr;
    if (!multicolSet->nextSiblingMultiColumnSet())
        return multicolSet;

    // This is potentially SLOW! But luckily very uncommon. You would have to dynamically insert a
    // spanner into the middle of column contents to need this.
    for (; multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
        LayoutObject* firstLayoutObject = firstLayoutObjectInSet(multicolSet);
        LayoutObject* lastLayoutObject = lastLayoutObjectInSet(multicolSet);
        ASSERT(firstLayoutObject);

        for (LayoutObject* walker = firstLayoutObject; walker; walker = walker->nextInPreOrder(this)) {
            if (walker == layoutObject)
                return multicolSet;
            if (walker == lastLayoutObject)
                break;
        }
    }

    return nullptr;
}
void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit offsetInFlowThread)
{
    if (!isPageLogicalHeightKnown()) {
        // If we have no clue about the height of the multicol container, bail. This situation
        // occurs initially when an auto-height multicol container is nested inside another
        // auto-height multicol container. We need at least an estimated height of the outer
        // multicol container before we can check what an inner fragmentainer group has room for.
        // Its height is indefinite for now.
        return;
    }
    LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offsetInFlowThread);
    if (columnSet->isInitialHeightCalculated()) {
        // We only insert additional fragmentainer groups in the initial layout pass. We only want
        // to balance columns in the last fragmentainer group (if we need to balance at all), so we
        // want that last fragmentainer group to be the same one in all layout passes that follow.
        return;
    }

    if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread)) {
        FragmentationContext* enclosingFragmentationContext = this->enclosingFragmentationContext();
        if (!enclosingFragmentationContext)
            return; // Not nested. We'll never need more rows than the one we already have then.
        ASSERT(!isLayoutPagedFlowThread());
        // We have run out of columns here, so we add another row to hold more columns. When we add
        // a new row, it implicitly means that we're inserting another column in our enclosing
        // multicol container. That in turn may mean that we've run out of columns there too.
        const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragmentainerGroup();
        if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragmentationContext->associatedFlowThread())
            enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.blockOffsetInEnclosingFragmentationContext());
    }
}
void LayoutMultiColumnFlowThread::skipColumnSpanner(LayoutBox* layoutObject, LayoutUnit logicalTopInFlowThread)
{
    ASSERT(layoutObject->isColumnSpanAll());
    LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlaceholder();
    LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox();
    if (previousColumnBox && previousColumnBox->isLayoutMultiColumnSet()) {
        LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(previousColumnBox);
        if (logicalTopInFlowThread < columnSet->logicalTopInFlowThread())
            logicalTopInFlowThread = columnSet->logicalTopInFlowThread(); // Negative margins may cause this.
        columnSet->endFlow(logicalTopInFlowThread);
    }
    LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox();
    if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) {
        LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox);
        m_lastSetWorkedOn = nextSet;
        nextSet->beginFlow(logicalTopInFlowThread);
    }

    // We'll lay out of spanners after flow thread layout has finished (during layout of the spanner
    // placeholders). There may be containing blocks for out-of-flow positioned descendants of the
    // spanner in the flow thread, so that out-of-flow objects inside the spanner will be laid out
    // as part of flow thread layout (even if the spanner itself won't). We need to add such
    // out-of-flow positioned objects to their containing blocks now, or they'll never get laid
    // out. Since it's non-trivial to determine if we need this, and where such out-of-flow objects
    // might be, just go through the whole subtree.
    for (LayoutObject* descendant = layoutObject->slowFirstChild(); descendant; descendant = descendant->nextInPreOrder()) {
        if (descendant->isBox() && descendant->isOutOfFlowPositioned())
            descendant->containingBlock()->insertPositionedObject(toLayoutBox(descendant));
    }
}
void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit bottomOffsetInFlowThread)
{
    if (!isPageLogicalHeightKnown()) {
        // If we have no clue about the height of the multicol container, bail. This situation
        // occurs initially when an auto-height multicol container is nested inside another
        // auto-height multicol container. We need at least an estimated height of the outer
        // multicol container before we can check what an inner fragmentainer group has room for.
        // Its height is indefinite for now.
        return;
    }
    // TODO(mstensho): bottomOffsetInFlowThread is an endpoint-exclusive offset, i.e. the offset
    // just after the bottom of some object. So, ideally, columnSetAtBlockOffset() should be
    // informed about this (i.e. take a PageBoundaryRule argument). This is not the only place with
    // this issue; see also pageRemainingLogicalHeightForOffset().
    LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(bottomOffsetInFlowThread);
    if (columnSet->isInitialHeightCalculated()) {
        // We only insert additional fragmentainer groups in the initial layout pass. We only want
        // to balance columns in the last fragmentainer group (if we need to balance at all), so we
        // want that last fragmentainer group to be the same one in all layout passes that follow.
        return;
    }

    if (!columnSet->hasFragmentainerGroupForColumnAt(bottomOffsetInFlowThread)) {
        FragmentationContext* enclosingFragmentationContext = this->enclosingFragmentationContext();
        if (!enclosingFragmentationContext)
            return; // Not nested. We'll never need more rows than the one we already have then.
        ASSERT(!isLayoutPagedFlowThread());
        // We have run out of columns here, so we add another row to hold more columns. When we add
        // a new row, it implicitly means that we're inserting another column in our enclosing
        // multicol container. That in turn may mean that we've run out of columns there too.
        const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragmentainerGroup();
        if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragmentationContext->associatedFlowThread())
            enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.blockOffsetInEnclosingFragmentationContext() + newRow.logicalHeight());
    }
}
LayoutSize LayoutMultiColumnFlowThread::flowThreadTranslationAtOffset(LayoutUnit offsetInFlowThread) const
{
    LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offsetInFlowThread);
    if (!columnSet)
        return LayoutSize(0, 0);
    return columnSet->flowThreadTranslationAtOffset(offsetInFlowThread);
}
LayoutMultiColumnSet* LayoutMultiColumnSet::createAnonymous(LayoutFlowThread& flowThread, const ComputedStyle& parentStyle)
{
    Document& document = flowThread.document();
    LayoutMultiColumnSet* layoutObject = new LayoutMultiColumnSet(&flowThread);
    layoutObject->setDocumentForAnonymous(&document);
    layoutObject->setStyle(ComputedStyle::createAnonymousStyleWithDisplay(parentStyle, BLOCK));
    return layoutObject;
}
LayoutUnit LayoutFlowThread::pageLogicalHeightForOffset(LayoutUnit offset)
{
    LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offset);
    if (!columnSet)
        return 0;

    return columnSet->pageLogicalHeight();
}
void LayoutFlowThread::collectLayerFragments(DeprecatedPaintLayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
{
    ASSERT(!m_columnSetsInvalidated);

    for (LayoutMultiColumnSetList::const_iterator iter = m_multiColumnSetList.begin(); iter != m_multiColumnSetList.end(); ++iter) {
        LayoutMultiColumnSet* columnSet = *iter;
        columnSet->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRect);
    }
}
示例#10
0
void LayoutFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
    computedValues.m_position = logicalTop;
    computedValues.m_extent = 0;

    for (LayoutMultiColumnSetList::const_iterator iter = m_multiColumnSetList.begin(); iter != m_multiColumnSetList.end(); ++iter) {
        LayoutMultiColumnSet* columnSet = *iter;
        computedValues.m_extent += columnSet->logicalHeightInFlowThread();
    }
}
void LayoutMultiColumnFlowThread::willBeRemovedFromTree()
{
    // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
    // are siblings of this object, and there may be pointers to this object's sibling somewhere
    // further up on the call stack.
    for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet())
        columnSet->detachFromFlowThread();
    multiColumnBlockFlow()->resetMultiColumnFlowThread();
    LayoutFlowThread::willBeRemovedFromTree();
}
void LayoutMultiColumnFlowThread::createAndInsertMultiColumnSet(LayoutBox* insertBefore)
{
    LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
    LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(*this, multicolContainer->styleRef());
    multicolContainer->LayoutBlock::addChild(newSet, insertBefore);
    invalidateColumnSets();

    // We cannot handle immediate column set siblings (and there's no need for it, either).
    // There has to be at least one spanner separating them.
    ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingMultiColumnBox()->isLayoutMultiColumnSet());
    ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColumnBox()->isLayoutMultiColumnSet());
}
bool MultiColumnFragmentainerGroup::recalculateColumnHeight(
    LayoutMultiColumnSet& columnSet) {
  LayoutUnit oldColumnHeight = m_columnHeight;

  m_maxColumnHeight = calculateMaxColumnHeight();

  // Only the last row may have auto height, and thus be balanced. There are no
  // good reasons to balance the preceding rows, and that could potentially lead
  // to an insane number of layout passes as well.
  if (isLastGroup() && columnSet.heightIsAuto()) {
    LayoutUnit newColumnHeight;
    if (!columnSet.isInitialHeightCalculated()) {
      // Initial balancing: Start with the lowest imaginable column height. Also
      // calculate the height of the tallest piece of unbreakable content.
      // Columns should never get any shorter than that (unless constrained by
      // max-height). Propagate this to our containing column set, in case there
      // is an outer multicol container that also needs to balance. After having
      // calculated the initial column height, the multicol container needs
      // another layout pass with the column height that we just calculated.
      InitialColumnHeightFinder initialHeightFinder(
          columnSet, logicalTopInFlowThread(), logicalBottomInFlowThread());
      LayoutUnit tallestUnbreakableLogicalHeight =
          initialHeightFinder.tallestUnbreakableLogicalHeight();
      columnSet.propagateTallestUnbreakableLogicalHeight(
          tallestUnbreakableLogicalHeight);
      newColumnHeight =
          std::max(initialHeightFinder.initialMinimalBalancedHeight(),
                   tallestUnbreakableLogicalHeight);
    } else {
      // Rebalancing: After having laid out again, we'll need to rebalance if
      // the height wasn't enough and we're allowed to stretch it, and then
      // re-lay out.  There are further details on the column balancing
      // machinery in ColumnBalancer and its derivates.
      newColumnHeight = rebalanceColumnHeightIfNeeded();
    }
    setAndConstrainColumnHeight(newColumnHeight);
  } else {
    // The position of the column set may have changed, in which case height
    // available for columns may have changed as well.
    setAndConstrainColumnHeight(m_columnHeight);
  }

  if (m_columnHeight == oldColumnHeight)
    return false;  // No change. We're done.

  return true;  // Need another pass.
}
示例#14
0
LayoutUnit LayoutFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule)
{
    LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offset);
    if (!columnSet)
        return 0;

    LayoutUnit pageLogicalTop = columnSet->pageLogicalTopForOffset(offset);
    LayoutUnit pageLogicalHeight = columnSet->pageLogicalHeight();
    LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
    LayoutUnit remainingHeight = pageLogicalBottom - offset;
    if (pageBoundaryRule == IncludePageBoundary) {
        // If IncludePageBoundary is set, the line exactly on the top edge of a
        // columnSet will act as being part of the previous columnSet.
        remainingHeight = intMod(remainingHeight, pageLogicalHeight);
    }
    return remainingHeight;
}
示例#15
0
ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet,
                               LayoutUnit logicalTopInFlowThread,
                               LayoutUnit logicalBottomInFlowThread)
    : m_columnSet(columnSet),
      m_logicalTopInFlowThread(logicalTopInFlowThread),
      m_logicalBottomInFlowThread(logicalBottomInFlowThread) {
  DCHECK_GE(columnSet.usedColumnCount(), 1U);
}
void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(LayoutBox* spannerObjectInFlowThread, LayoutObject* insertedBeforeInFlowThread)
{
    LayoutBox* insertBeforeColumnBox = nullptr;
    LayoutMultiColumnSet* setToSplit = nullptr;
    if (insertedBeforeInFlowThread) {
        // The spanner is inserted before something. Figure out what this entails. If the
        // next object is a spanner too, it means that we can simply insert a new spanner
        // placeholder in front of its placeholder.
        insertBeforeColumnBox = insertedBeforeInFlowThread->spannerPlaceholder();
        if (!insertBeforeColumnBox) {
            // The next object isn't a spanner; it's regular column content. Examine what
            // comes right before us in the flow thread, then.
            LayoutObject* previousLayoutObject = previousInPreOrderSkippingOutOfFlow(this, spannerObjectInFlowThread);
            if (!previousLayoutObject || previousLayoutObject == this) {
                // The spanner is inserted as the first child of the multicol container,
                // which means that we simply insert a new spanner placeholder at the
                // beginning.
                insertBeforeColumnBox = firstMultiColumnBox();
            } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder = containingColumnSpannerPlaceholder(previousLayoutObject)) {
                // Before us is another spanner. We belong right after it then.
                insertBeforeColumnBox = previousPlaceholder->nextSiblingMultiColumnBox();
            } else {
                // We're inside regular column content with both feet. Find out which column
                // set this is. It needs to be split it into two sets, so that we can insert
                // a new spanner placeholder between them.
                setToSplit = mapDescendantToColumnSet(previousLayoutObject);
                ASSERT(setToSplit == mapDescendantToColumnSet(insertedBeforeInFlowThread));
                insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox();
                // We've found out which set that needs to be split. Now proceed to
                // inserting the spanner placeholder, and then insert a second column set.
            }
        }
        ASSERT(setToSplit || insertBeforeColumnBox);
    }

    LayoutBlockFlow* multicolContainer = multiColumnBlockFlow();
    LayoutMultiColumnSpannerPlaceholder* newPlaceholder = LayoutMultiColumnSpannerPlaceholder::createAnonymous(multicolContainer->styleRef(), *spannerObjectInFlowThread);
    ASSERT(!insertBeforeColumnBox || insertBeforeColumnBox->parent() == multicolContainer);
    multicolContainer->LayoutBlock::addChild(newPlaceholder, insertBeforeColumnBox);
    spannerObjectInFlowThread->setSpannerPlaceholder(*newPlaceholder);

    if (setToSplit)
        createAndInsertMultiColumnSet(insertBeforeColumnBox);
}
bool LayoutMultiColumnFlowThread::recalculateColumnHeights()
{
    // All column sets that needed layout have now been laid out, so we can finally validate them.
    validateColumnSets();

    if (!m_needsColumnHeightsRecalculation)
        return false;

    // Column heights may change here because of balancing. We may have to do multiple layout
    // passes, depending on how the contents is fitted to the changed column heights. In most
    // cases, laying out again twice or even just once will suffice. Sometimes we need more
    // passes than that, though, but the number of retries should not exceed the number of
    // columns, unless we have a bug.
    bool needsRelayout = false;
    for (LayoutMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet())
        needsRelayout |= multicolSet->recalculateColumnHeight();

    if (needsRelayout)
        setChildNeedsLayout(MarkOnlyThis);

    m_inBalancingPass = needsRelayout;
    return needsRelayout;
}
示例#18
0
InitialColumnHeightFinder::InitialColumnHeightFinder(
    const LayoutMultiColumnSet& columnSet,
    LayoutUnit logicalTopInFlowThread,
    LayoutUnit logicalBottomInFlowThread)
    : ColumnBalancer(columnSet,
                     logicalTopInFlowThread,
                     logicalBottomInFlowThread) {
  m_shortestStruts.resize(columnSet.usedColumnCount());
  for (auto& strut : m_shortestStruts)
    strut = LayoutUnit::max();
  traverse();
  // We have now found each explicit / forced break, and their location. Now we
  // need to figure out how many additional implicit / soft breaks we need and
  // guess where they will occur, in order
  // to provide an initial column height.
  distributeImplicitBreaks();
}
void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(LayoutObject* descendant)
{
    // This method ensures that the list of column sets and spanner placeholders reflects the
    // multicol content that we'll be left with after removal of a descendant (or descendant
    // subtree). See the header file for more information. Removing content may mean that we need to
    // remove column sets and/or spanner placeholders.
    if (m_isBeingEvacuated)
        return;
    if (shouldSkipInsertedOrRemovedChild(this, *descendant))
        return;
    bool hadContainingPlaceholder = containingColumnSpannerPlaceholder(descendant);
    bool processedSomething = false;
    LayoutObject* next;
    // Remove spanner placeholders that are no longer needed, and merge column sets around them.
    for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = next) {
        if (layoutObject != descendant && shouldSkipInsertedOrRemovedChild(this, *layoutObject)) {
            next = layoutObject->nextInPreOrderAfterChildren(descendant);
            continue;
        }
        processedSomething = true;
        LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spannerPlaceholder();
        if (!placeholder) {
            next = layoutObject->nextInPreOrder(descendant);
            continue;
        }
        next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a spanner. Its children are of no interest to us.
        destroySpannerPlaceholder(placeholder);
    }
    if (hadContainingPlaceholder || !processedSomething)
        return; // No column content will be removed, so we can stop here.

    // Column content will be removed. Does this mean that we should destroy a column set?
    LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = nullptr;
    LayoutObject* previousLayoutObject = previousInPreOrderSkippingOutOfFlow(this, descendant);
    if (previousLayoutObject && previousLayoutObject != this) {
        adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(previousLayoutObject);
        if (!adjacentPreviousSpannerPlaceholder)
            return; // Preceded by column content. Set still needed.
    }
    LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = nullptr;
    LayoutObject* nextLayoutObject = nextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant);
    if (nextLayoutObject) {
        adjacentNextSpannerPlaceholder = containingColumnSpannerPlaceholder(nextLayoutObject);
        if (!adjacentNextSpannerPlaceholder)
            return; // Followed by column content. Set still needed.
    }
    // We have now determined that, with the removal of |descendant|, we should remove a column
    // set. Locate it and remove it. Do it without involving mapDescendantToColumnSet(), as that
    // might be very slow. Deduce the right set from the spanner placeholders that we've already
    // found.
    LayoutMultiColumnSet* columnSetToRemove;
    if (adjacentNextSpannerPlaceholder) {
        columnSetToRemove = toLayoutMultiColumnSet(adjacentNextSpannerPlaceholder->previousSiblingMultiColumnBox());
        ASSERT(!adjacentPreviousSpannerPlaceholder || columnSetToRemove == adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox());
    } else if (adjacentPreviousSpannerPlaceholder) {
        columnSetToRemove = toLayoutMultiColumnSet(adjacentPreviousSpannerPlaceholder->nextSiblingMultiColumnBox());
    } else {
        // If there were no adjacent spanners, it has to mean that there's only one column set,
        // since it's only spanners that may cause creation of multiple sets.
        columnSetToRemove = firstMultiColumnSet();
        ASSERT(columnSetToRemove);
        ASSERT(!columnSetToRemove->nextSiblingMultiColumnSet());
    }
    ASSERT(columnSetToRemove);
    columnSetToRemove->destroy();
}
void LayoutMultiColumnFlowThread::columnRuleStyleDidChange()
{
    for (LayoutMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet())
        columnSet->setShouldDoFullPaintInvalidation(PaintInvalidationStyleChange);
}