blob: ca0d9bfebb3985a05e60ea5777ff79946091b7f8 [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 "third_party/blink/renderer/core/paint/block_flow_paint_invalidator.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
namespace blink {
void BlockFlowPaintInvalidator::InvalidatePaintForOverhangingFloatsInternal(
InvalidateDescendantMode invalidate_descendants) {
// Invalidate paint of any overhanging floats (if we know we're the one to
// paint them). Otherwise, bail out.
if (!block_flow_.HasOverhangingFloats())
return;
for (const auto& floating_object : block_flow_.GetFloatingObjects()->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 (block_flow_.IsOverhangingFloat(*floating_object) &&
!floating_object->GetLayoutObject()->HasSelfPaintingLayer() &&
(floating_object->ShouldPaint() ||
(invalidate_descendants == kInvalidateDescendants &&
floating_object->GetLayoutObject()->IsDescendantOf(&block_flow_)))) {
LayoutBox* floating_box = floating_object->GetLayoutObject();
floating_box->SetShouldDoFullPaintInvalidation();
auto* floating_block_flow = DynamicTo<LayoutBlockFlow>(floating_box);
if (floating_block_flow)
BlockFlowPaintInvalidator(*floating_block_flow)
.InvalidatePaintForOverhangingFloatsInternal(
kDontInvalidateDescendants);
}
}
}
void BlockFlowPaintInvalidator::InvalidateDisplayItemClients(
PaintInvalidationReason reason) {
ObjectPaintInvalidator object_paint_invalidator(block_flow_);
object_paint_invalidator.InvalidateDisplayItemClient(block_flow_, reason);
const NGPaintFragment* paint_fragment = block_flow_.PaintFragment();
if (paint_fragment) {
object_paint_invalidator.InvalidateDisplayItemClient(*paint_fragment,
reason);
}
// PaintInvalidationRectangle happens when we invalidate the caret.
// The later conditions don't apply when we invalidate the caret or the
// selection.
if (reason == PaintInvalidationReason::kRectangle ||
reason == PaintInvalidationReason::kSelection)
return;
NGInlineCursor cursor(block_flow_);
if (cursor) {
// Line boxes record hit test data (see NGBoxFragmentPainter::PaintLineBox)
// and should be invalidated if they change.
bool invalidate_all_lines = block_flow_.HasEffectiveAllowedTouchAction();
for (cursor.MoveToFirstLine(); cursor; cursor.MoveToNextLine()) {
// The first line NGLineBoxFragment paints the ::first-line background.
// Because it may be expensive to figure out if the first line is affected
// by any ::first-line selectors at all, we just invalidate
// unconditionally which is typically cheaper.
if (invalidate_all_lines || cursor.Current().UsesFirstLineStyle()) {
DCHECK(cursor.Current().GetDisplayItemClient());
object_paint_invalidator.InvalidateDisplayItemClient(
*cursor.Current().GetDisplayItemClient(), reason);
}
if (!invalidate_all_lines)
break;
}
} else if (RootInlineBox* line = block_flow_.FirstRootBox()) {
// 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.
if (line->IsFirstLineStyle()) {
object_paint_invalidator.InvalidateDisplayItemClient(*line, reason);
}
}
if (block_flow_.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 = block_flow_.FirstChild(); child;
child = child->NextSibling()) {
if (child->IsLayoutMultiColumnSet() &&
!child->ShouldDoFullPaintInvalidation())
object_paint_invalidator.InvalidateDisplayItemClient(*child, reason);
}
}
}
} // namespace blink