Commit 0fc08b4f authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[PE] Update subtree paint properties on fragments change

When an object's fragments change, e.g.
- the object moved from one fragment to another fragment of the
  flow thread;
- the object resized and created more or less fragments
etc., we need to update paint properties of the subtree.

The new logic also covers the previous SetNeedsPaintPropertyUpdate
logic for multicols.

Bug: 817803
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Ib641c1e5ef5af7d93b8fb8de70cdc9aae2382fc9
Reviewed-on: https://chromium-review.googlesource.com/953566Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#542356}
parent 597c1e88
<!DOCTYPE html>
<div style="background: green; width: 80px; height: 80px"></div>
<!DOCTYPE html>
<div style="columns: 4; height: 100px; width: 400px; column-gap: 0">
<div id="before" style="display: inline-block; width: 50px; height: 300px; background: red"></div>
<svg style="background: green; width: 80px; height: 80px"></svg>
</div>
<script src="../../resources/run-after-layout-and-paint.js"></script>
<script>
runAfterLayoutAndPaint(() => {
before.style.display = 'none';
}, true);
</script>
......@@ -1813,6 +1813,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
void SetNeedsPaintPropertyUpdate() {
layout_object_.SetNeedsPaintPropertyUpdate();
}
void SetSubtreeNeedsPaintPropertyUpdate() {
layout_object_.SetSubtreeNeedsPaintPropertyUpdate();
}
void SetPartialInvalidationRect(const LayoutRect& r) {
layout_object_.SetPartialInvalidationRect(r);
......
......@@ -1637,33 +1637,10 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
}
void FragmentPaintPropertyTreeBuilder::SetNeedsPaintPropertyUpdateIfNeeded() {
if (!object_.IsBoxModelObject())
return;
const auto& box_model_object = ToLayoutBoxModelObject(object_);
if (box_model_object.Layer() &&
box_model_object.Layer()->ShouldFragmentCompositedBounds()) {
// Always force-update properties for fragmented content.
// TODO(chrishtr): find ways to optimize this in the future.
// It may suffice to compare previous and current visual overflow,
// but we do not currenly cache that on the LayoutObject or PaintLayer.
object_.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
return;
}
if (!object_.IsBox())
return;
const LayoutBox& box = ToLayoutBox(object_);
// Always force-update properties for fragmented content. Boxes with
// control clip have a fragment-aware offset.
if (box.HasControlClip() && !box.Layer() &&
full_context_.painting_layer->EnclosingPaginationLayer()) {
box.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
return;
}
if (box.Size() == box.PreviousSize())
return;
......@@ -2212,6 +2189,7 @@ void ObjectPaintPropertyTreeBuilder::CreateFragmentContexts(
FragmentData* current_fragment_data = nullptr;
FragmentainerIterator iterator(flow_thread,
object_bounding_box_in_flow_thread);
bool fragments_changed = false;
Vector<PaintPropertyTreeBuilderFragmentContext, 1> new_fragment_contexts;
for (; !iterator.AtEnd(); iterator.Advance()) {
auto pagination_offset = ToLayoutPoint(iterator.PaginationOffset());
......@@ -2244,10 +2222,20 @@ void ObjectPaintPropertyTreeBuilder::CreateFragmentContexts(
new_fragment_contexts.push_back(
ContextForFragment(fragment_clip, logical_top_in_flow_thread));
current_fragment_data =
current_fragment_data
? &current_fragment_data->EnsureNextFragment()
: &object_.GetMutableForPainting().FirstFragment();
Optional<LayoutUnit> old_logical_top_in_flow_thread;
if (current_fragment_data) {
if (const auto* old_fragment = current_fragment_data->NextFragment())
old_logical_top_in_flow_thread = old_fragment->LogicalTopInFlowThread();
current_fragment_data = &current_fragment_data->EnsureNextFragment();
} else {
current_fragment_data = &object_.GetMutableForPainting().FirstFragment();
old_logical_top_in_flow_thread =
current_fragment_data->LogicalTopInFlowThread();
}
if (!old_logical_top_in_flow_thread ||
*old_logical_top_in_flow_thread != logical_top_in_flow_thread)
fragments_changed = true;
InitFragmentPaintProperties(
*current_fragment_data,
......@@ -2259,9 +2247,15 @@ void ObjectPaintPropertyTreeBuilder::CreateFragmentContexts(
// This will be an empty fragment - get rid of it?
InitSingleFragmentFromParent(needs_paint_properties);
} else {
if (current_fragment_data->NextFragment())
fragments_changed = true;
current_fragment_data->ClearNextFragment();
context_.fragments = std::move(new_fragment_contexts);
}
// Need to update subtree paint properties for the changed fragments.
if (fragments_changed)
object_.GetMutableForPainting().SetSubtreeNeedsPaintPropertyUpdate();
}
bool ObjectPaintPropertyTreeBuilder::UpdateFragments() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment