Commit 53bbe9b0 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[CI] ScopedBoxContentsPaintState and ScopedReplacedContentsPaintState

Previously we adjusted local border box properties out of
LayoutBlock::PaintObject(), while adjusted cull rect and paint offset
inside of LayoutBlock::PaintObject(), making inconsistent relationship
among paint chunk properties, cull rect and paint offset between the
two adjustments. We should adjust them altogether to ensure consistence.

Now rename PaintInfoWithOffset to ScopedPaintState (which will include
more paint property adjustment in the future), and combine ScopedBoxClipper
and the original code that adjusts cull rect and paint offset for
ScrollTranslation into ScopedBoxContentsPaintState.

Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I70f1ad00f2508d80eaa387259a1a62f301016ee5
Reviewed-on: https://chromium-review.googlesource.com/1213824Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589971}
parent 12f2cd31
......@@ -18,12 +18,12 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutTextControl INPUT id='target'",
"object": "LayoutNGBlockFlow DIV",
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
"object": "LayoutTextControl INPUT id='target'",
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
......
......@@ -18,14 +18,14 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='target'",
"object": "NGPhysicalTextFragment ' FAIL .'",
"rect": [8, 8, 100, 19],
"reason": "chunk appeared"
"reason": "disappeared"
},
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='target'",
"object": "NGPhysicalTextFragment ' PASS .'",
"rect": [8, 8, 100, 19],
"reason": "chunk disappeared"
"reason": "appeared"
}
]
}
......
......@@ -18,14 +18,14 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='t'",
"object": "NGPhysicalTextFragment 'Passed'",
"rect": [8, 136, 43, 17],
"reason": "chunk appeared"
"reason": "appeared"
},
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='t'",
"object": "NGPhysicalTextFragment 'Failed'",
"rect": [8, 136, 39, 17],
"reason": "chunk disappeared"
"reason": "disappeared"
}
]
}
......
......@@ -23,7 +23,7 @@
"reason": "selection"
},
{
"object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV id='t'",
"object": "LayoutNGBlockFlow DIV id='t'",
"rect": [8, 27, 197, 1],
"reason": "incremental"
}
......
......@@ -147,8 +147,6 @@ blink_core_sources("paint") {
"object_painter_base.h",
"paint_event.h",
"paint_info.h",
"paint_info_with_offset.cc",
"paint_info_with_offset.h",
"paint_invalidator.cc",
"paint_invalidator.h",
"paint_layer.cc",
......@@ -184,8 +182,8 @@ blink_core_sources("paint") {
"root_inline_box_painter.h",
"rounded_inner_rect_clipper.cc",
"rounded_inner_rect_clipper.h",
"scoped_box_clipper.cc",
"scoped_box_clipper.h",
"scoped_paint_state.cc",
"scoped_paint_state.h",
"scoped_svg_paint_state.cc",
"scoped_svg_paint_state.h",
"scrollable_area_painter.cc",
......
......@@ -16,9 +16,8 @@
#include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/scoped_box_clipper.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
......@@ -28,19 +27,12 @@ namespace blink {
DISABLE_CFI_PERF
void BlockPainter::Paint(const PaintInfo& paint_info) {
PaintInfoWithOffset paint_info_with_offset(layout_block_, paint_info);
// We can't early return if there is no fragment to paint for this block,
// because there may be overflowing children that exist in the painting
// fragment. We also can't check ShouldPaint() in the case because we
// don't have a meaningful paint offset. TODO(wangxianzhu): only paint
// children if !adjustment.FragmentToPaint().
if (paint_info_with_offset.FragmentToPaint() &&
!ShouldPaint(paint_info_with_offset))
ScopedPaintState paint_state(layout_block_, paint_info);
if (!ShouldPaint(paint_state))
return;
auto paint_offset = paint_info_with_offset.PaintOffset();
auto& local_paint_info = paint_info_with_offset.MutablePaintInfo();
auto paint_offset = paint_state.PaintOffset();
auto& local_paint_info = paint_state.MutablePaintInfo();
PaintPhase original_phase = local_paint_info.phase;
if (original_phase == PaintPhase::kOutline) {
......@@ -52,12 +44,14 @@ void BlockPainter::Paint(const PaintInfo& paint_info) {
local_paint_info.phase = PaintPhase::kDescendantBlockBackgroundsOnly;
}
if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly) {
base::Optional<ScopedBoxClipper> box_clipper;
if (local_paint_info.phase != PaintPhase::kMask)
box_clipper.emplace(layout_block_, local_paint_info);
if (original_phase == PaintPhase::kMask) {
layout_block_.PaintObject(local_paint_info, paint_offset);
} else if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly) {
ScopedBoxContentsPaintState contents_paint_state(paint_state,
layout_block_);
layout_block_.PaintObject(contents_paint_state.GetPaintInfo(),
contents_paint_state.PaintOffset());
}
// Carets are painted in the foreground phase, outside of the contents
......@@ -238,42 +232,13 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
if (paint_phase != PaintPhase::kSelfOutlineOnly &&
paint_phase != PaintPhase::kSelfBlockBackgroundOnly &&
paint_phase != PaintPhase::kMask) {
// Handle scrolling translation.
base::Optional<PaintInfo> scrolled_paint_info;
auto contents_paint_offset = paint_offset;
if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
const auto* object_properties = fragment->PaintProperties();
auto* scroll_translation =
object_properties ? object_properties->ScrollTranslation() : nullptr;
if (scroll_translation) {
scrolled_paint_info.emplace(paint_info);
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
scrolled_paint_info->UpdateCullRectForScrollingContents(
EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
scroll_translation->Matrix().ToAffineTransform());
} else {
scrolled_paint_info->UpdateCullRect(
scroll_translation->Matrix().ToAffineTransform());
}
// See comments for ScrollTranslation in object_paint_properties.h
// for the reason of adding ScrollOrigin(). contents_paint_offset will
// be used only for the scrolling contents that are not painted through
// descendant objects' Paint() method, e.g. inline boxes.
// TODO(wangxianzhu): Encapsulate such logic at various places into
// one class.
contents_paint_offset += layout_block_.ScrollOrigin();
}
}
const PaintInfo& contents_paint_info =
scrolled_paint_info ? *scrolled_paint_info : paint_info;
// Actually paint the contents.
if (layout_block_.IsLayoutBlockFlow()) {
// All floating descendants will be LayoutBlockFlow objects, and will get
// painted here. That is step #5 of the CSS spec (see above).
PaintBlockFlowContents(contents_paint_info, contents_paint_offset);
PaintBlockFlowContents(paint_info, paint_offset);
} else {
PaintContents(contents_paint_info, contents_paint_offset);
PaintContents(paint_info, paint_offset);
}
}
......@@ -350,10 +315,17 @@ void BlockPainter::PaintCarets(const PaintInfo& paint_info,
}
DISABLE_CFI_PERF
bool BlockPainter::ShouldPaint(
const PaintInfoWithOffset& paint_info_with_offset) const {
bool BlockPainter::ShouldPaint(const ScopedPaintState& paint_state) const {
// If there is no fragment to paint for this block, we still need to continue
// the paint tree walk in case there are overflowing children that exist in
// the current painting fragment of the painting layer. In the case we can't
// check the overflow rect against the cull rect in the case because we don't
// know the paint offset.
if (!paint_state.FragmentToPaint())
return true;
LayoutRect overflow_rect;
if (paint_info_with_offset.GetPaintInfo().IsPrinting() &&
if (paint_state.GetPaintInfo().IsPrinting() &&
layout_block_.IsAnonymousBlock() && layout_block_.ChildrenInline()) {
// For case <a href="..."><div>...</div></a>, when layout_block_ is the
// anonymous container of <a>, the anonymous container's visual overflow is
......@@ -381,7 +353,7 @@ bool BlockPainter::ShouldPaint(
overflow_rect.Move(-layout_block_.ScrolledContentOffset());
}
return paint_info_with_offset.LocalRectIntersectsCullRect(overflow_rect);
return paint_state.LocalRectIntersectsCullRect(overflow_rect);
}
void BlockPainter::PaintContents(const PaintInfo& paint_info,
......
......@@ -10,7 +10,7 @@
namespace blink {
struct PaintInfo;
class PaintInfoWithOffset;
class ScopedPaintState;
class InlineBox;
class LayoutBlock;
class LayoutBox;
......@@ -31,14 +31,12 @@ class BlockPainter {
void PaintOverflowControlsIfNeeded(const PaintInfo&,
const LayoutPoint& paint_offset);
// See ObjectPainter::paintAllPhasesAtomically().
// See ObjectPainter::PaintAllPhasesAtomically().
void PaintAllChildPhasesAtomically(const LayoutBox&, const PaintInfo&);
static void PaintChildrenOfFlexibleBox(const LayoutFlexibleBox&,
const PaintInfo&);
static void PaintInlineBox(const InlineBox&, const PaintInfo&);
bool ShouldPaint(const PaintInfoWithOffset&) const;
private:
// Paint scroll hit test placeholders in the correct paint order (see:
// ScrollHitTestDisplayItem.h).
......@@ -50,6 +48,8 @@ class BlockPainter {
void PaintBlockFlowContents(const PaintInfo&, const LayoutPoint&);
void PaintCarets(const PaintInfo&, const LayoutPoint& paint_offset);
bool ShouldPaint(const ScopedPaintState&) const;
const LayoutBlock& layout_block_;
};
......
......@@ -19,7 +19,7 @@
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
......@@ -33,8 +33,8 @@ namespace blink {
void BoxPainter::Paint(const PaintInfo& paint_info) {
// Default implementation. Just pass paint through to the children.
PaintInfoWithOffset paint_info_with_offset(layout_box_, paint_info);
PaintChildren(paint_info_with_offset.GetPaintInfo());
ScopedPaintState paint_state(layout_box_, paint_info);
PaintChildren(paint_state.GetPaintInfo());
}
void BoxPainter::PaintChildren(const PaintInfo& paint_info) {
......@@ -53,7 +53,7 @@ void BoxPainter::PaintChildren(const PaintInfo& paint_info) {
void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
LayoutRect paint_rect;
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
base::Optional<ScopedBoxContentsPaintState> contents_paint_state;
if (BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
&layout_box_, paint_info)) {
......@@ -62,41 +62,31 @@ void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
// overflow rect.
paint_rect = layout_box_.PhysicalLayoutOverflowRect();
const auto* fragment = paint_info.FragmentToPaint(layout_box_);
if (!fragment)
return;
scoped_scroll_property.emplace(
paint_info.context.GetPaintController(), fragment->ContentsProperties(),
layout_box_, DisplayItem::PaintPhaseToScrollType(paint_info.phase));
// See comments for ScrollTranslation in object_paint_properties.h for the
// reason of moving by ScrollOrigin(). TODO(wangxianzhu): Encapsulate such
// logic at various places into one class.
paint_rect.MoveBy(layout_box_.ScrollOrigin());
contents_paint_state.emplace(paint_info, paint_offset, layout_box_);
paint_rect.MoveBy(contents_paint_state->PaintOffset());
// The background painting code assumes that the borders are part of the
// paintRect so we expand the paintRect by the border size when painting the
// background into the scrolling contents layer.
// paint_rect so we expand the paint_rect by the border size when painting
// the background into the scrolling contents layer.
paint_rect.Expand(layout_box_.BorderBoxOutsets());
} else {
paint_rect = layout_box_.BorderBoxRect();
paint_rect.MoveBy(paint_offset);
}
paint_rect.MoveBy(paint_offset);
PaintBoxDecorationBackgroundWithRect(paint_info, paint_rect);
PaintBoxDecorationBackgroundWithRect(
contents_paint_state ? contents_paint_state->GetPaintInfo() : paint_info,
paint_rect);
}
LayoutRect BoxPainter::BoundsForDrawingRecorder(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
bool BoxPainter::BackgroundIsKnownToBeOpaque(const PaintInfo& paint_info) {
LayoutRect bounds =
BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
&layout_box_, paint_info)
? layout_box_.LayoutOverflowRect()
: layout_box_.SelfVisualOverflowRect();
bounds.MoveBy(paint_offset);
return bounds;
return layout_box_.BackgroundIsKnownToBeOpaqueInRect(bounds);
}
void BoxPainter::PaintBoxDecorationBackgroundWithRect(
......@@ -138,10 +128,7 @@ void BoxPainter::PaintBoxDecorationBackgroundWithRect(
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
LayoutRect(EnclosingIntRect(paint_rect)) == paint_rect &&
// TODO(wkorman): Rename BoundsForDrawingRecorder as it's used
// here for another purpose.
layout_box_.BackgroundIsKnownToBeOpaqueInRect(
BoundsForDrawingRecorder(paint_info, LayoutPoint())))
BackgroundIsKnownToBeOpaque(paint_info))
recorder.SetKnownToBeOpaque();
bool needs_end_layer = false;
......
......@@ -34,10 +34,8 @@ class BoxPainter {
void PaintMaskImages(const PaintInfo&, const LayoutRect&);
void PaintBoxDecorationBackgroundWithRect(const PaintInfo&,
const LayoutRect&);
LayoutRect BoundsForDrawingRecorder(const PaintInfo&,
const LayoutPoint& paint_offset);
private:
bool BackgroundIsKnownToBeOpaque(const PaintInfo&);
void PaintBackground(const PaintInfo&,
const LayoutRect&,
const Color& background_color,
......
......@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
namespace blink {
......@@ -350,10 +350,10 @@ void CollapsedBorderPainter::PaintCollapsedBorders(
// Now left=start_, right=end_, before_=top, after_=bottom.
// Collapsed borders are half inside and half outside of |rect|.
PaintInfoWithOffset paint_info_with_offset(cell_, paint_info);
ScopedPaintState paint_state(cell_, paint_info);
IntRect rect = PixelSnappedIntRect(
TableCellPainter(cell_).PaintRectNotIncludingVisualOverflow(
paint_info_with_offset.PaintOffset()));
paint_state.PaintOffset()));
// |paint_rect| covers the whole collapsed borders.
IntRect paint_rect = rect;
paint_rect.Expand(IntRectOutsets(before_.outer_width, end_.outer_width,
......
......@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/layout/layout_details_marker.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
......@@ -25,19 +25,18 @@ void DetailsMarkerPainter::Paint(const PaintInfo& paint_info) {
paint_info.context, layout_details_marker_, paint_info.phase))
return;
PaintInfoWithOffset paint_info_with_offset(layout_details_marker_,
paint_info);
if (!paint_info_with_offset.LocalRectIntersectsCullRect(
ScopedPaintState paint_state(layout_details_marker_, paint_info);
if (!paint_state.LocalRectIntersectsCullRect(
layout_details_marker_.PhysicalVisualOverflowRect()))
return;
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
const auto& local_paint_info = paint_state.GetPaintInfo();
DrawingRecorder recorder(local_paint_info.context, layout_details_marker_,
local_paint_info.phase);
const Color color(layout_details_marker_.ResolveColor(GetCSSPropertyColor()));
local_paint_info.context.SetFillColor(color);
auto box_origin = paint_info_with_offset.PaintOffset();
auto box_origin = paint_state.PaintOffset();
box_origin.Move(
layout_details_marker_.BorderLeft() +
layout_details_marker_.PaddingLeft(),
......
......@@ -10,7 +10,6 @@
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/replaced_painter.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
......
......@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
#include "third_party/blink/renderer/core/layout/layout_frame_set.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
......@@ -154,10 +154,10 @@ void FrameSetPainter::Paint(const PaintInfo& paint_info) {
if (!child)
return;
PaintInfoWithOffset paint_info_with_offset(layout_frame_set_, paint_info);
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
ScopedPaintState paint_state(layout_frame_set_, paint_info);
const auto& local_paint_info = paint_state.GetPaintInfo();
PaintChildren(local_paint_info);
PaintBorders(local_paint_info, paint_info_with_offset.PaintOffset());
PaintBorders(local_paint_info, paint_state.PaintOffset());
}
} // namespace blink
......@@ -17,7 +17,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
......@@ -62,8 +62,8 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info) {
if (path.IsEmpty())
return;
PaintInfoWithOffset paint_info_with_offset(layout_image_, paint_info);
auto paint_offset = paint_info_with_offset.PaintOffset();
ScopedPaintState paint_state(layout_image_, paint_info);
auto paint_offset = paint_state.PaintOffset();
path.Translate(FloatSize(paint_offset.X(), paint_offset.Y()));
if (DrawingRecorder::UseCachedDrawingIfPossible(
......
......@@ -10,15 +10,15 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
namespace blink {
void InlinePainter::Paint(const PaintInfo& paint_info) {
PaintInfoWithOffset paint_info_with_offset(layout_inline_, paint_info);
auto paint_offset = paint_info_with_offset.PaintOffset();
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
ScopedPaintState paint_state(layout_inline_, paint_info);
auto paint_offset = paint_state.PaintOffset();
const auto& local_paint_info = paint_state.GetPaintInfo();
if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
// Inline box with self painting layer is painted in this code path.
......
......@@ -9,7 +9,7 @@
#include "third_party/blink/renderer/core/layout/list_marker_text.h"
#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
#include "third_party/blink/renderer/core/paint/text_painter.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
......@@ -61,13 +61,13 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info) {
paint_info.context, layout_list_marker_, paint_info.phase))
return;
PaintInfoWithOffset paint_info_with_offset(layout_list_marker_, paint_info);
if (!paint_info_with_offset.LocalRectIntersectsCullRect(
ScopedPaintState paint_state(layout_list_marker_, paint_info);
if (!paint_state.LocalRectIntersectsCullRect(
layout_list_marker_.PhysicalVisualOverflowRect()))
return;
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
auto box_origin = paint_info_with_offset.PaintOffset();
const auto& local_paint_info = paint_state.GetPaintInfo();
auto box_origin = paint_state.PaintOffset();
DrawingRecorder recorder(local_paint_info.context, layout_list_marker_,
local_paint_info.phase);
......
......@@ -30,10 +30,9 @@
#include "third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_phase.h"
#include "third_party/blink/renderer/core/paint/scoped_box_clipper.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
......@@ -142,15 +141,15 @@ NGBoxFragmentPainter::NGBoxFragmentPainter(const NGPaintFragment& box)
}
void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
PaintInfoWithOffset paint_info_with_offset(box_fragment_, paint_info);
if (!ShouldPaint(paint_info_with_offset))
ScopedPaintState paint_state(box_fragment_, paint_info);
if (!ShouldPaint(paint_state))
return;
PaintInfo& info = paint_info_with_offset.MutablePaintInfo();
PaintInfo& info = paint_state.MutablePaintInfo();
if (PhysicalFragment().IsAtomicInline())
return PaintAtomicInline(info);
LayoutPoint paint_offset = paint_info_with_offset.PaintOffset();
LayoutPoint paint_offset = paint_state.PaintOffset();
PaintPhase original_phase = info.phase;
if (original_phase == PaintPhase::kOutline) {
......@@ -164,13 +163,17 @@ void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly) {
base::Optional<ScopedBoxClipper> box_clipper;
if (original_phase == PaintPhase::kForeground ||
original_phase == PaintPhase::kFloat ||
original_phase == PaintPhase::kDescendantOutlinesOnly) {
box_clipper.emplace(box_fragment_, info);
if ((original_phase == PaintPhase::kForeground ||
original_phase == PaintPhase::kFloat ||
original_phase == PaintPhase::kDescendantOutlinesOnly) &&
box_fragment_.GetLayoutObject()->IsBox()) {
ScopedBoxContentsPaintState contents_paint_state(
paint_state, ToLayoutBox(*box_fragment_.GetLayoutObject()));
PaintObject(contents_paint_state.GetPaintInfo(),
contents_paint_state.PaintOffset());
} else {
PaintObject(info, paint_offset);
}
PaintObject(info, paint_offset);
}
if (ShouldPaintSelfOutline(original_phase)) {
......@@ -222,51 +225,18 @@ void NGBoxFragmentPainter::PaintObject(
}
if (paint_phase != PaintPhase::kSelfOutlineOnly) {
// TODO(layout-dev): Figure out where paint properties should live.
const auto& layout_object = *box_fragment_.GetLayoutObject();
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
base::Optional<PaintInfo> scrolled_paint_info;
auto contents_paint_offset = paint_offset;
if (const auto* fragment = paint_info.FragmentToPaint(layout_object)) {
const auto* object_properties = fragment->PaintProperties();
auto* scroll_translation =
object_properties ? object_properties->ScrollTranslation() : nullptr;
if (scroll_translation) {
scoped_scroll_property.emplace(
paint_info.context.GetPaintController(), scroll_translation,
box_fragment_, DisplayItem::PaintPhaseToScrollType(paint_phase));
scrolled_paint_info.emplace(paint_info);
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
scrolled_paint_info->UpdateCullRectForScrollingContents(
EnclosingIntRect(PhysicalFragment().OverflowClipRect(
paint_offset, kIgnorePlatformOverlayScrollbarSize)),
scroll_translation->Matrix().ToAffineTransform());
} else {
scrolled_paint_info->UpdateCullRect(
scroll_translation->Matrix().ToAffineTransform());
}
// See comments for ScrollTranslation in object_paint_properties.h for
// the reason of adding ScrollOrigin().
contents_paint_offset += ToLayoutBox(layout_object).ScrollOrigin();
}
}
const PaintInfo& contents_paint_info =
scrolled_paint_info ? *scrolled_paint_info : paint_info;
if (PhysicalFragment().ChildrenInline()) {
if (PhysicalFragment().IsBlockFlow()) {
PaintBlockFlowContents(contents_paint_info, contents_paint_offset);
PaintBlockFlowContents(paint_info, paint_offset);
if (paint_phase == PaintPhase::kFloat ||
paint_phase == PaintPhase::kSelection ||
paint_phase == PaintPhase::kTextClip)
PaintFloats(contents_paint_info);
PaintFloats(paint_info);
} else {
PaintInlineChildren(box_fragment_.Children(), contents_paint_info,
contents_paint_offset);
PaintInlineChildren(box_fragment_.Children(), paint_info, paint_offset);
}
} else {
PaintBlockChildren(contents_paint_info);
PaintBlockChildren(paint_info);
}
if (ShouldPaintDescendantOutlines(paint_phase)) {
NGFragmentPainter(box_fragment_)
......@@ -562,9 +532,9 @@ void NGBoxFragmentPainter::PaintInlineChildBoxUsingLegacyFallback(
void NGBoxFragmentPainter::PaintAllPhasesAtomically(
const PaintInfo& paint_info,
bool is_self_painting) {
PaintInfoWithOffset paint_info_with_offset(box_fragment_, paint_info);
auto paint_offset = paint_info_with_offset.PaintOffset();
PaintInfo& local_paint_info = paint_info_with_offset.MutablePaintInfo();
ScopedPaintState paint_state(box_fragment_, paint_info);
auto paint_offset = paint_state.PaintOffset();
PaintInfo& local_paint_info = paint_state.MutablePaintInfo();
// Pass PaintPhaseSelection and PaintPhaseTextClip is handled by the regular
// foreground paint implementation. We don't need complete painting for these
......@@ -586,11 +556,17 @@ void NGBoxFragmentPainter::PaintAllPhasesAtomically(
}
local_paint_info.phase = PaintPhase::kFloat;
PaintObject(local_paint_info, paint_offset);
{
ScopedBoxClipper box_clipper(box_fragment_, local_paint_info);
local_paint_info.phase = PaintPhase::kForeground;
local_paint_info.phase = PaintPhase::kForeground;
if (box_fragment_.GetLayoutObject()->IsBox()) {
ScopedBoxContentsPaintState contents_paint_state(
paint_state, ToLayoutBox(*box_fragment_.GetLayoutObject()));
PaintObject(contents_paint_state.GetPaintInfo(),
contents_paint_state.PaintOffset());
} else {
PaintObject(local_paint_info, paint_offset);
}
local_paint_info.phase = PaintPhase::kOutline;
PaintObject(local_paint_info, paint_offset);
......@@ -775,9 +751,9 @@ void NGBoxFragmentPainter::PaintOverflowControlsIfNeeded(
}
bool NGBoxFragmentPainter::ShouldPaint(
const PaintInfoWithOffset& paint_info_with_offset) const {
const ScopedPaintState& paint_state) const {
// TODO(layout-dev): Add support for scrolling, see BlockPainter::ShouldPaint.
return paint_info_with_offset.LocalRectIntersectsCullRect(
return paint_state.LocalRectIntersectsCullRect(
box_fragment_.SelfInkOverflow());
}
......
......@@ -23,7 +23,7 @@ class HitTestResult;
class LayoutRect;
class NGPaintFragment;
class NGPhysicalFragment;
class PaintInfoWithOffset;
class ScopedPaintState;
struct PaintInfo;
// Painter for LayoutNG box fragments, paints borders and background. Delegates
......@@ -67,7 +67,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
bool IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
const NGPaintFragment&,
const PaintInfo&);
bool ShouldPaint(const PaintInfoWithOffset&) const;
bool ShouldPaint(const ScopedPaintState&) const;
void PaintBoxDecorationBackground(const PaintInfo&,
const LayoutPoint& paint_offset);
......
......@@ -11,9 +11,9 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
......@@ -22,6 +22,67 @@
namespace blink {
namespace {
// Adjusts cull rect and paint chunk properties of the input ScopedPaintState
// for ReplacedContentTransform if needed.
class ScopedReplacedContentPaintState : public ScopedPaintState {
public:
ScopedReplacedContentPaintState(const ScopedPaintState& input,
const LayoutReplaced& replaced);
};
ScopedReplacedContentPaintState::ScopedReplacedContentPaintState(
const ScopedPaintState& input,
const LayoutReplaced& replaced)
: ScopedPaintState(input) {
if (!fragment_to_paint_)
return;
const auto* paint_properties = fragment_to_paint_->PaintProperties();
if (!paint_properties)
return;
PropertyTreeState new_properties =
input_paint_info_.context.GetPaintController()
.CurrentPaintChunkProperties();
bool property_changed = false;
const auto* content_transform = paint_properties->ReplacedContentTransform();
if (content_transform && replaced.IsSVGRoot()) {
new_properties.SetTransform(content_transform);
adjusted_paint_info_.emplace(input_paint_info_);
DCHECK(content_transform->Matrix().IsAffine());
adjusted_paint_info_->UpdateCullRect(
content_transform->Matrix().ToAffineTransform());
property_changed = true;
}
bool painter_implements_content_box_clip = replaced.IsLayoutImage();
if (paint_properties->OverflowClip() &&
(!painter_implements_content_box_clip ||
replaced.StyleRef().HasBorderRadius())) {
new_properties.SetClip(paint_properties->OverflowClip());
property_changed = true;
}
// Check filter for optimized image policy violation highlights, which
// may be applied locally.
if (paint_properties->Filter() &&
(!replaced.HasLayer() || !replaced.Layer()->IsSelfPaintingLayer())) {
new_properties.SetEffect(paint_properties->Filter());
property_changed = true;
}
if (property_changed) {
chunk_properties_.emplace(input_paint_info_.context.GetPaintController(),
new_properties, replaced,
input_paint_info_.DisplayItemTypeForClipping());
}
}
} // anonymous namespace
void ReplacedPainter::Paint(const PaintInfo& paint_info) {
// TODO(crbug.com/797779): For now embedded contents don't know whether
// they are painted in a fragmented context and may do something bad in a
......@@ -34,12 +95,12 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
cache_skipper.emplace(paint_info.context);
}
PaintInfoWithOffset paint_info_with_offset(layout_replaced_, paint_info);
if (!ShouldPaint(paint_info_with_offset))
ScopedPaintState paint_state(layout_replaced_, paint_info);
if (!ShouldPaint(paint_state))
return;
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
auto paint_offset = paint_info_with_offset.PaintOffset();
const auto& local_paint_info = paint_state.GetPaintInfo();
auto paint_offset = paint_state.PaintOffset();
LayoutRect border_rect(paint_offset, layout_replaced_.Size());
if (ShouldPaintSelfBlockBackground(local_paint_info.phase)) {
......@@ -84,54 +145,14 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
bool skip_clip = layout_replaced_.IsSVGRoot() &&
!ToLayoutSVGRoot(layout_replaced_).ShouldApplyViewportClip();
if (skip_clip || !layout_replaced_.PhysicalContentBoxRect().IsEmpty()) {
PaintInfo transformed_paint_info = local_paint_info;
base::Optional<ScopedPaintChunkProperties> chunk_properties;
if (const auto* fragment = paint_info.FragmentToPaint(layout_replaced_)) {
if (const auto* paint_properties = fragment->PaintProperties()) {
PropertyTreeState new_properties =
local_paint_info.context.GetPaintController()
.CurrentPaintChunkProperties();
bool property_changed = false;
if (paint_properties->ReplacedContentTransform() &&
layout_replaced_.IsSVGRoot()) {
new_properties.SetTransform(
paint_properties->ReplacedContentTransform());
DCHECK(paint_properties->ReplacedContentTransform()
->Matrix()
.IsAffine());
transformed_paint_info.UpdateCullRect(
paint_properties->ReplacedContentTransform()
->Matrix()
.ToAffineTransform());
property_changed = true;
}
bool painter_implements_content_box_clip =
layout_replaced_.IsLayoutImage();
if (paint_properties->OverflowClip() &&
(!painter_implements_content_box_clip ||
layout_replaced_.StyleRef().HasBorderRadius())) {
new_properties.SetClip(paint_properties->OverflowClip());
property_changed = true;
}
// Check filter for optimized image policy violation highlights, which
// may be applied locally.
if (paint_properties->Filter() &&
(!layout_replaced_.HasLayer() ||
!layout_replaced_.Layer()->IsSelfPaintingLayer())) {
new_properties.SetEffect(paint_properties->Filter());
property_changed = true;
}
if (property_changed) {
chunk_properties.emplace(
local_paint_info.context.GetPaintController(), new_properties,
layout_replaced_, paint_info.DisplayItemTypeForClipping());
}
}
ScopedReplacedContentPaintState content_paint_state(paint_state,
layout_replaced_);
if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
RecordHitTestData(content_paint_state.GetPaintInfo(),
content_paint_state.PaintOffset());
}
if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
RecordHitTestData(paint_info, paint_offset);
layout_replaced_.PaintReplaced(transformed_paint_info, paint_offset);
layout_replaced_.PaintReplaced(content_paint_state.GetPaintInfo(),
content_paint_state.PaintOffset());
}
if (layout_replaced_.CanResize()) {
......@@ -184,9 +205,8 @@ void ReplacedPainter::RecordHitTestData(const PaintInfo& paint_info,
TouchActionRect(rect, touch_action));
}
bool ReplacedPainter::ShouldPaint(
const PaintInfoWithOffset& paint_info_with_offset) const {
const auto& paint_info = paint_info_with_offset.GetPaintInfo();
bool ReplacedPainter::ShouldPaint(const ScopedPaintState& paint_state) const {
const auto& paint_info = paint_state.GetPaintInfo();
if (paint_info.phase != PaintPhase::kForeground &&
!ShouldPaintSelfOutline(paint_info.phase) &&
paint_info.phase != PaintPhase::kSelection &&
......@@ -207,7 +227,7 @@ bool ReplacedPainter::ShouldPaint(
LayoutRect local_rect(layout_replaced_.VisualOverflowRect());
local_rect.Unite(layout_replaced_.LocalSelectionRect());
layout_replaced_.FlipForWritingMode(local_rect);
if (!paint_info_with_offset.LocalRectIntersectsCullRect(local_rect))
if (!paint_state.LocalRectIntersectsCullRect(local_rect))
return false;
return true;
......
......@@ -11,7 +11,7 @@
namespace blink {
struct PaintInfo;
class PaintInfoWithOffset;
class ScopedPaintState;
class LayoutReplaced;
class ReplacedPainter {
......@@ -23,7 +23,7 @@ class ReplacedPainter {
void Paint(const PaintInfo&);
bool ShouldPaint(const PaintInfoWithOffset&) const;
bool ShouldPaint(const ScopedPaintState&) const;
private:
// Paint a hit test display item and record hit test data. This should be
......
// Copyright 2014 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/scoped_box_clipper.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
namespace blink {
DISABLE_CFI_PERF
ScopedBoxClipper::ScopedBoxClipper(const LayoutBox& box,
const PaintInfo& paint_info) {
InitializeScopedProperties(paint_info.FragmentToPaint(box), box, paint_info);
}
DISABLE_CFI_PERF
ScopedBoxClipper::ScopedBoxClipper(const NGPaintFragment& fragment,
const PaintInfo& paint_info) {
DCHECK(fragment.GetLayoutObject());
InitializeScopedProperties(
paint_info.FragmentToPaint(*fragment.GetLayoutObject()), fragment,
paint_info);
}
void ScopedBoxClipper::InitializeScopedProperties(
const FragmentData* fragment_data,
const DisplayItemClient& client,
const PaintInfo& paint_info) {
DCHECK(paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly &&
paint_info.phase != PaintPhase::kSelfOutlineOnly &&
paint_info.phase != PaintPhase::kMask);
if (!fragment_data || !fragment_data->HasLocalBorderBoxProperties())
return;
const PropertyTreeState& contents_properties =
fragment_data->ContentsProperties();
scoped_properties_.emplace(paint_info.context.GetPaintController(),
contents_properties, client,
paint_info.DisplayItemTypeForClipping());
}
} // namespace blink
// Copyright 2014 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_BOX_CLIPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_BOX_CLIPPER_H_
#include "base/optional.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
class DisplayItemClient;
class FragmentData;
class LayoutBox;
class NGPaintFragment;
struct PaintInfo;
// Within the scope of this object:
// - OverflowClip is applied if it exists
// - If it doesn't exist, then InnerBorderRadiusClip is applied if it exists.
// - If it doesn't exist, then properties are not modified.
// TODO(vmpstr): It should be possible to make this apply ContentsProperties
// instead of a contents clip only. However, there are situation where the
// LocalBorderBoxProperties().Clip(), which would be the fallback if neither
// OverflowClip nor InnerBorderRadiusClip exist, is not the correct clip to
// apply. We need to audit the usage to figure in which situations we want
// BoxClipper and in which situations we want OverflowClip or
// InnerBorderRadiusClip only.
class ScopedBoxClipper {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
ScopedBoxClipper(const LayoutBox&, const PaintInfo&);
ScopedBoxClipper(const NGPaintFragment&, const PaintInfo&);
private:
void InitializeScopedProperties(const FragmentData*,
const DisplayItemClient&,
const PaintInfo&);
base::Optional<ScopedPaintChunkProperties> scoped_properties_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_BOX_BOX_CLIPPER_H_
......@@ -2,11 +2,15 @@
// 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/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
namespace blink {
void PaintInfoWithOffset::AdjustForPaintOffsetTranslation(
void ScopedPaintState::AdjustForPaintOffsetTranslation(
const LayoutObject& object,
const TransformPaintPropertyNode* paint_offset_translation) {
if (input_paint_info_.context.InDrawingRecorder()) {
......@@ -28,15 +32,59 @@ void PaintInfoWithOffset::AdjustForPaintOffsetTranslation(
}
adjusted_paint_info_.emplace(input_paint_info_);
DCHECK(paint_offset_translation->Matrix().IsAffine());
adjusted_paint_info_->UpdateCullRect(
paint_offset_translation->Matrix().ToAffineTransform());
}
void PaintInfoWithOffset::FinishPaintOffsetTranslationAsDrawing() {
void ScopedPaintState::FinishPaintOffsetTranslationAsDrawing() {
// This scope should not interlace with scopes of DrawingRecorders.
DCHECK(paint_offset_translation_as_drawing_);
DCHECK(input_paint_info_.context.InDrawingRecorder());
input_paint_info_.context.Restore();
}
void ScopedBoxContentsPaintState::AdjustForBoxContents(const LayoutBox& box) {
DCHECK((input_paint_info_.phase != PaintPhase::kSelfBlockBackgroundOnly ||
BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
&box, input_paint_info_)) &&
input_paint_info_.phase != PaintPhase::kSelfOutlineOnly &&
input_paint_info_.phase != PaintPhase::kMask);
if (!fragment_to_paint_ || !fragment_to_paint_->HasLocalBorderBoxProperties())
return;
DCHECK_EQ(paint_offset_, fragment_to_paint_->PaintOffset());
chunk_properties_.emplace(input_paint_info_.context.GetPaintController(),
fragment_to_paint_->ContentsProperties(), box,
input_paint_info_.DisplayItemTypeForClipping());
// Then adjust paint offset and cull rect for scroll translation.
const auto* properties = fragment_to_paint_->PaintProperties();
if (!properties)
return;
const auto* scroll_translation = properties->ScrollTranslation();
if (!scroll_translation)
return;
// See comments for ScrollTranslation in object_paint_properties.h
// for the reason of adding ScrollOrigin(). contents_paint_offset will
// be used only for the scrolling contents that are not painted through
// descendant objects' Paint() method, e.g. inline boxes.
paint_offset_ += box.ScrollOrigin();
adjusted_paint_info_.emplace(input_paint_info_);
DCHECK(scroll_translation->Matrix().IsAffine());
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
adjusted_paint_info_->UpdateCullRectForScrollingContents(
EnclosingIntRect(box.OverflowClipRect(paint_offset_)),
scroll_translation->Matrix().ToAffineTransform());
} else {
adjusted_paint_info_->UpdateCullRect(
scroll_translation->Matrix().ToAffineTransform());
}
}
} // namespace blink
......@@ -2,37 +2,52 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INFO_WITH_OFFSET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INFO_WITH_OFFSET_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_PAINT_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_PAINT_STATE_H_
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
namespace blink {
// Adjusts cull rect of the input PaintInfo and finds the paint offset for a
// LayoutObject or an NGPaintFragment before painting. Normally a
// Paint(const PaintInfo&) method creates an PaintInfoWithOffset and holds it
// in the stack, and passes it to other PaintXXX() methods that paint different
// parts of the object.
class PaintInfoWithOffset {
// Adjusts paint chunk properties, cull rect of the input PaintInfo and finds
// the paint offset for a LayoutObject or an NGPaintFragment before painting.
//
// Normally a Paint(const PaintInfo&) method creates an ScopedPaintState and
// holds it in the stack, and pass its GetPaintInfo() and PaintOffset() to the
// other PaintXXX() methods that paint different parts of the object.
// TODO(wangxianzhu): Would it be better if ScopedPaintState was passed to
// PaintXXX() methods instead of (const PaintInfo&, const LayoutPoint&)?
//
// Each object create its own ScopedPaintState, so ScopedPaintState created for
// one object won't be passed to another object. Instead, PaintInfo is passed
// between objects.
class ScopedPaintState {
STACK_ALLOCATED();
public:
PaintInfoWithOffset(const LayoutObject& object, const PaintInfo& paint_info)
ScopedPaintState(const LayoutObject& object, const PaintInfo& paint_info)
: fragment_to_paint_(paint_info.FragmentToPaint(object)),
input_paint_info_(paint_info) {
if (!fragment_to_paint_) {
// The object has nothing to paint in the current fragment.
// TODO(wangxianzhu): Use DCHECK(fragment_to_paint_) in PaintOffset()
// when all painters check FragmentToPaint() before painting.
paint_offset_ = LayoutPoint(
LayoutPoint(LayoutUnit::NearlyMax(), LayoutUnit::NearlyMax()));
return;
}
paint_offset_ = fragment_to_paint_->PaintOffset();
if (&object == paint_info.PaintContainer()) {
// PaintLayerPainter already adjusted for PaintOffsetTranslation for
// PaintContainer. TODO(wangxianzhu): Can we combine the code?
return;
}
// TODO(wangxianzhu): Combine code for other paint properties into this
// class, then the following will be something like
// AdjustForLocalBorcerBoxProperties().
const auto* properties = fragment_to_paint_->PaintProperties();
if (properties && properties->PaintOffsetTranslation()) {
AdjustForPaintOffsetTranslation(object,
......@@ -40,11 +55,10 @@ class PaintInfoWithOffset {
}
}
PaintInfoWithOffset(const NGPaintFragment& fragment,
const PaintInfo& paint_info)
: PaintInfoWithOffset(*fragment.GetLayoutObject(), paint_info) {}
ScopedPaintState(const NGPaintFragment& fragment, const PaintInfo& paint_info)
: ScopedPaintState(*fragment.GetLayoutObject(), paint_info) {}
~PaintInfoWithOffset() {
~ScopedPaintState() {
if (paint_offset_translation_as_drawing_)
FinishPaintOffsetTranslationAsDrawing();
}
......@@ -59,16 +73,16 @@ class PaintInfoWithOffset {
return *adjusted_paint_info_;
}
LayoutPoint PaintOffset() const {
// TODO(wangxianzhu): Use DCHECK(fragment_to_paint_) when all painters
// check FragmentToPaint() before painting.
return fragment_to_paint_
? fragment_to_paint_->PaintOffset()
: LayoutPoint(LayoutUnit::NearlyMax(), LayoutUnit::NearlyMax());
}
LayoutPoint PaintOffset() const { return paint_offset_; }
const FragmentData* FragmentToPaint() const { return fragment_to_paint_; }
LayoutRect LocalCullRect() const {
auto cull_rect = LayoutRect(GetPaintInfo().GetCullRect().Rect());
cull_rect.MoveBy(-PaintOffset());
return cull_rect;
}
bool LocalRectIntersectsCullRect(const LayoutRect& local_rect) const {
LayoutRect rect_in_paint_info_space = local_rect;
rect_in_paint_info_space.MoveBy(PaintOffset());
......@@ -76,6 +90,21 @@ class PaintInfoWithOffset {
rect_in_paint_info_space);
}
protected:
// Constructors for subclasses to create the initial state before adjustment.
ScopedPaintState(const ScopedPaintState& input)
: fragment_to_paint_(input.fragment_to_paint_),
input_paint_info_(input.GetPaintInfo()),
paint_offset_(input.PaintOffset()) {}
// TODO(wangxianzhu): Remove this constructor when we pass ScopedPaintState to
// PaintXXX() methods of the same object.
ScopedPaintState(const PaintInfo& paint_info,
const LayoutPoint& paint_offset,
const LayoutObject& object)
: fragment_to_paint_(paint_info.FragmentToPaint(object)),
input_paint_info_(paint_info),
paint_offset_(paint_offset) {}
private:
void AdjustForPaintOffsetTranslation(
const LayoutObject&,
......@@ -83,13 +112,38 @@ class PaintInfoWithOffset {
void FinishPaintOffsetTranslationAsDrawing();
protected:
const FragmentData* fragment_to_paint_;
const PaintInfo& input_paint_info_;
LayoutPoint paint_offset_;
base::Optional<PaintInfo> adjusted_paint_info_;
base::Optional<ScopedPaintChunkProperties> chunk_properties_;
bool paint_offset_translation_as_drawing_ = false;
};
// Adjusts paint chunk properties, cull rect and paint offset of the input
// ScopedPaintState for box contents if needed.
class ScopedBoxContentsPaintState : public ScopedPaintState {
public:
ScopedBoxContentsPaintState(const ScopedPaintState& input,
const LayoutBox& box)
: ScopedPaintState(input) {
AdjustForBoxContents(box);
}
// TODO(wangxianzhu): Remove this constructor when we pass ScopedPaintState to
// PaintXXX() methods of the same object.
ScopedBoxContentsPaintState(const PaintInfo& paint_info,
const LayoutPoint& paint_offset,
const LayoutBox& box)
: ScopedPaintState(paint_info, paint_offset, box) {
AdjustForBoxContents(box);
}
private:
void AdjustForBoxContents(const LayoutBox&);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INFO_WITH_OFFSET_H_
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCOPED_PAINT_STATE_H_
......@@ -12,7 +12,7 @@
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
......@@ -32,11 +32,10 @@ void TableCellPainter::PaintContainerBackgroundBehindCell(
!layout_table_cell_.FirstChild())
return;
PaintInfoWithOffset paint_info_with_offset(layout_table_cell_, paint_info);
ScopedPaintState paint_state(layout_table_cell_, paint_info);
auto paint_rect =
PaintRectNotIncludingVisualOverflow(paint_info_with_offset.PaintOffset());
PaintBackground(paint_info_with_offset.GetPaintInfo(), paint_rect,
background_object);
PaintRectNotIncludingVisualOverflow(paint_state.PaintOffset());
PaintBackground(paint_state.GetPaintInfo(), paint_rect, background_object);
}
void TableCellPainter::PaintBackground(const PaintInfo& paint_info,
......
......@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/core/paint/collapsed_border_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
......@@ -50,10 +50,9 @@ void TableRowPainter::Paint(const PaintInfo& paint_info) {
void TableRowPainter::PaintOutline(const PaintInfo& paint_info) {
DCHECK(ShouldPaintSelfOutline(paint_info.phase));
PaintInfoWithOffset paint_info_with_offset(layout_table_row_, paint_info);
ScopedPaintState paint_state(layout_table_row_, paint_info);
ObjectPainter(layout_table_row_)
.PaintOutline(paint_info_with_offset.GetPaintInfo(),
paint_info_with_offset.PaintOffset());
.PaintOutline(paint_state.GetPaintInfo(), paint_state.PaintOffset());
}
void TableRowPainter::HandleChangedPartialPaint(
......@@ -78,14 +77,14 @@ void TableRowPainter::PaintBoxDecorationBackground(
HandleChangedPartialPaint(paint_info, dirtied_columns);
PaintInfoWithOffset paint_info_with_offset(layout_table_row_, paint_info);
ScopedPaintState paint_state(layout_table_row_, paint_info);
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, layout_table_row_,
DisplayItem::kBoxDecorationBackground))
return;
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
auto paint_offset = paint_info_with_offset.PaintOffset();
const auto& local_paint_info = paint_state.GetPaintInfo();
auto paint_offset = paint_state.PaintOffset();
DrawingRecorder recorder(local_paint_info.context, layout_table_row_,
DisplayItem::kBoxDecorationBackground);
LayoutRect paint_rect(paint_offset, layout_table_row_.Size());
......
......@@ -13,9 +13,8 @@
#include "third_party/blink/renderer/core/paint/collapsed_border_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/scoped_box_clipper.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h"
#include "third_party/blink/renderer/core/paint/table_row_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
......@@ -65,17 +64,20 @@ void TableSectionPainter::PaintSection(const PaintInfo& paint_info) {
if (!total_rows || !total_cols)
return;
PaintInfoWithOffset paint_info_with_offset(layout_table_section_, paint_info);
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
auto paint_offset = paint_info_with_offset.PaintOffset();
ScopedPaintState paint_state(layout_table_section_, paint_info);
const auto& local_paint_info = paint_state.GetPaintInfo();
auto paint_offset = paint_state.PaintOffset();
if (local_paint_info.phase != PaintPhase::kSelfOutlineOnly) {
base::Optional<ScopedBoxClipper> box_clipper;
if (local_paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly &&
local_paint_info.phase != PaintPhase::kMask) {
box_clipper.emplace(layout_table_section_, local_paint_info);
ScopedBoxContentsPaintState contents_paint_state(paint_state,
layout_table_section_);
PaintObject(contents_paint_state.GetPaintInfo(),
contents_paint_state.PaintOffset());
} else {
PaintObject(local_paint_info, paint_offset);
}
PaintObject(local_paint_info, paint_offset);
}
if (ShouldPaintSelfOutline(local_paint_info.phase)) {
......@@ -127,12 +129,15 @@ void TableSectionPainter::PaintCollapsedSectionBorders(
!layout_table_section_.Table()->EffectiveColumns().size())
return;
PaintInfoWithOffset paint_info_with_offset(layout_table_section_, paint_info);
const auto& local_paint_info = paint_info_with_offset.GetPaintInfo();
auto paint_offset = paint_info_with_offset.PaintOffset();
base::Optional<ScopedBoxClipper> box_clipper;
if (local_paint_info.phase != PaintPhase::kMask)
box_clipper.emplace(layout_table_section_, local_paint_info);
ScopedPaintState paint_state(layout_table_section_, paint_info);
base::Optional<ScopedBoxContentsPaintState> contents_paint_state;
if (paint_info.phase != PaintPhase::kMask)
contents_paint_state.emplace(paint_state, layout_table_section_);
const auto& local_paint_info = contents_paint_state
? contents_paint_state->GetPaintInfo()
: paint_state.GetPaintInfo();
auto paint_offset = contents_paint_state ? contents_paint_state->PaintOffset()
: paint_state.PaintOffset();
CellSpan dirtied_rows;
CellSpan dirtied_columns;
......@@ -143,7 +148,7 @@ void TableSectionPainter::PaintCollapsedSectionBorders(
dirtied_columns = layout_table_section_.FullTableEffectiveColumnSpan();
} else {
layout_table_section_.DirtiedRowsAndEffectiveColumns(
TableAlignedRect(paint_info, paint_offset), dirtied_rows,
TableAlignedRect(local_paint_info, paint_offset), dirtied_rows,
dirtied_columns);
}
......
......@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info_with_offset.h"
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
......@@ -38,11 +38,11 @@ void TextControlSingleLinePainter::Paint(const PaintInfo& paint_info) {
}
// Convert the rect into the coords used for painting the content.
PaintInfoWithOffset paint_info_with_offset(text_control_, paint_info);
contents_rect.MoveBy(paint_info_with_offset.PaintOffset());
ScopedPaintState paint_state(text_control_, paint_info);
contents_rect.MoveBy(paint_state.PaintOffset());
IntRect snapped_rect = PixelSnappedIntRect(contents_rect);
LayoutTheme::GetTheme().Painter().PaintCapsLockIndicator(
text_control_, paint_info_with_offset.GetPaintInfo(), snapped_rect);
text_control_, paint_state.GetPaintInfo(), snapped_rect);
}
} // namespace blink
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