blob: 84fed48255919b79ec7288af193f569b377b34d7 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/paint/BlockFlowPaintInvalidator.h"
#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/LayoutInline.h"
#include "core/paint/BoxPaintInvalidator.h"
#include "core/paint/PaintInvalidator.h"
namespace blink {
void BlockFlowPaintInvalidator::invalidatePaintForOverhangingFloatsInternal(
InvalidateDescendantMode invalidateDescendants) {
// Invalidate paint of any overhanging floats (if we know we're the one to
// paint them). Otherwise, bail out.
if (!m_blockFlow.hasOverhangingFloats())
return;
for (const auto& floatingObject : m_blockFlow.floatingObjects()->set()) {
// Only issue paint invalidations for the object if it is overhanging, is
// not in its own layer, and is our responsibility to paint (m_shouldPaint
// is set). When paintAllDescendants is true, the latter condition is
// replaced with being a descendant of us.
if (m_blockFlow.isOverhangingFloat(*floatingObject) &&
!floatingObject->layoutObject()->hasSelfPaintingLayer() &&
(floatingObject->shouldPaint() ||
(invalidateDescendants == InvalidateDescendants &&
floatingObject->layoutObject()->isDescendantOf(&m_blockFlow)))) {
LayoutBox* floatingBox = floatingObject->layoutObject();
floatingBox->setShouldDoFullPaintInvalidation();
if (floatingBox->isLayoutBlockFlow())
BlockFlowPaintInvalidator(*toLayoutBlockFlow(floatingBox))
.invalidatePaintForOverhangingFloatsInternal(
DontInvalidateDescendants);
}
}
}
void BlockFlowPaintInvalidator::invalidateDisplayItemClients(
PaintInvalidationReason reason) {
ObjectPaintInvalidator objectPaintInvalidator(m_blockFlow);
objectPaintInvalidator.invalidateDisplayItemClient(m_blockFlow, reason);
// PaintInvalidationRectangle happens when we invalidate the caret.
// The later conditions don't apply when we invalidate the caret or the
// selection.
if (reason == PaintInvalidationRectangle ||
reason == PaintInvalidationSelection)
return;
// If the block is a continuation or containing block of an inline
// continuation, invalidate the start object of the continuations if it has
// focus ring because change of continuation may change the shape of the focus
// ring.
if (m_blockFlow.isAnonymous()) {
LayoutObject* startOfContinuations = nullptr;
if (LayoutInline* inlineElementContinuation =
m_blockFlow.inlineElementContinuation()) {
// This block is an anonymous block continuation.
startOfContinuations = inlineElementContinuation->node()->layoutObject();
} else if (LayoutObject* firstChild = m_blockFlow.firstChild()) {
// This block is the anonymous containing block of an inline element
// continuation.
if (firstChild->isElementContinuation())
startOfContinuations = firstChild->node()->layoutObject();
}
if (startOfContinuations &&
startOfContinuations->styleRef().outlineStyleIsAuto())
ObjectPaintInvalidator(*startOfContinuations)
.slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
*startOfContinuations, reason);
}
RootInlineBox* line = m_blockFlow.firstRootBox();
if (line && line->isFirstLineStyle()) {
// It's the RootInlineBox that paints the ::first-line background. Note that
// since it may be expensive to figure out if the first line is affected by
// any ::first-line selectors at all, we just invalidate it unconditionally
// which is typically cheaper.
objectPaintInvalidator.invalidateDisplayItemClient(*line, reason);
}
if (m_blockFlow.multiColumnFlowThread()) {
// Invalidate child LayoutMultiColumnSets which may need to repaint column
// rules after m_blockFlow's column rule style and/or layout changed.
for (LayoutObject* child = m_blockFlow.firstChild(); child;
child = child->nextSibling()) {
if (child->isLayoutMultiColumnSet() &&
!child->shouldDoFullPaintInvalidation())
objectPaintInvalidator.invalidateDisplayItemClient(*child, reason);
}
}
}
} // namespace blink