Commit 08c1894f authored by Alison Maher's avatar Alison Maher Committed by Commit Bot

Backplate paint phase

This change adds a paint phase for backplates in forced colors mode.
The backplate paint phase goes before the float and foreground paint
phases and after the background paint phase.

The new paint phase has been added for both the backplate
implementation for LayoutNG and non-LayoutNG.

Bug: 970285
Change-Id: I51badafa9564b6e477ab794fed9b8e2caee4b441
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1757271Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Reviewed-by: default avatarKevin Babbitt <kbabbitt@microsoft.com>
Commit-Queue: Alison Maher <almaher@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#693759}
parent 1bec8fe2
......@@ -180,6 +180,7 @@ void BlockPainter::PaintAllChildPhasesAtomically(const LayoutBox& child,
void BlockPainter::PaintInlineBox(const InlineBox& inline_box,
const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kForcedColorsModeBackplate &&
paint_info.phase != PaintPhase::kSelection)
return;
......@@ -232,6 +233,14 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
if (ShouldPaintSelfBlockBackground(paint_phase))
layout_block_.PaintBoxDecorationBackground(paint_info, paint_offset);
// Draw a backplate behind all text if in forced colors mode.
if (paint_phase == PaintPhase::kForcedColorsModeBackplate &&
layout_block_.GetFrame()->GetDocument()->InForcedColorsMode() &&
layout_block_.ChildrenInline()) {
LineBoxListPainter(To<LayoutBlockFlow>(layout_block_).LineBoxes())
.PaintBackplate(layout_block_, paint_info, paint_offset);
}
// If we're in any phase except *just* the self (outline or background) or a
// mask, paint children now. This is step #5, 7, 8, and 9 of the CSS spec (see
// above).
......@@ -270,11 +279,8 @@ void BlockPainter::PaintBlockFlowContents(const PaintInfo& paint_info,
} else if (ShouldPaintDescendantOutlines(paint_info.phase)) {
ObjectPainter(layout_block_).PaintInlineChildrenOutlines(paint_info);
} else {
LineBoxListPainter painter(To<LayoutBlockFlow>(layout_block_).LineBoxes());
// Draw a backplate behind all text if forced colors mode is enabled.
if (layout_block_.GetFrame()->GetDocument()->InForcedColorsMode())
painter.PaintBackplate(layout_block_, paint_info, paint_offset);
painter.Paint(layout_block_, paint_info, paint_offset);
LineBoxListPainter(To<LayoutBlockFlow>(layout_block_).LineBoxes())
.Paint(layout_block_, paint_info, paint_offset);
}
// If we don't have any floats to paint, or we're in the wrong paint phase,
......
......@@ -97,13 +97,6 @@ bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
DCHECK(!ShouldPaintSelfOutline(paint_info.phase) &&
!ShouldPaintDescendantOutlines(paint_info.phase));
// Only paint during the foreground/selection phases.
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kTextClip &&
paint_info.phase != PaintPhase::kMask)
return false;
// The only way an inline could paint like this is if it has a layer.
DCHECK(layout_object.IsLayoutBlock() ||
(layout_object.IsLayoutInline() && layout_object.HasLayer()));
......@@ -127,6 +120,13 @@ bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
// Only paint during the foreground/selection phases.
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kTextClip &&
paint_info.phase != PaintPhase::kMask)
return;
if (!ShouldPaint(layout_object, paint_info, paint_offset))
return;
......@@ -161,7 +161,8 @@ void LineBoxListPainter::PaintBackplate(
const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
if (!ShouldPaint(layout_object, paint_info, paint_offset))
if (paint_info.phase != PaintPhase::kForcedColorsModeBackplate ||
!ShouldPaint(layout_object, paint_info, paint_offset))
return;
// Only paint backplates behind text when forced-color-adjust is auto.
......
......@@ -247,6 +247,7 @@ void NGBoxFragmentPainter::PaintInternal(const PaintInfo& paint_info) {
original_phase != PaintPhase::kSelfOutlineOnly) {
if ((original_phase == PaintPhase::kForeground ||
original_phase == PaintPhase::kFloat ||
original_phase == PaintPhase::kForcedColorsModeBackplate ||
original_phase == PaintPhase::kDescendantOutlinesOnly) &&
box_fragment_.GetLayoutObject()->IsBox()) {
ScopedBoxContentsPaintState contents_paint_state(
......@@ -856,6 +857,9 @@ void NGBoxFragmentPainter::PaintAllPhasesAtomically(
local_paint_info.phase = PaintPhase::kBlockBackground;
PaintInternal(local_paint_info);
local_paint_info.phase = PaintPhase::kForcedColorsModeBackplate;
PaintInternal(local_paint_info);
local_paint_info.phase = PaintPhase::kFloat;
PaintInternal(local_paint_info);
......@@ -906,6 +910,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
const PhysicalOffset& paint_offset) {
// Only paint during the foreground/selection phases.
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kForcedColorsModeBackplate &&
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kTextClip &&
paint_info.phase != PaintPhase::kMask &&
......@@ -939,8 +944,11 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
}
}
if (layout_block.GetDocument().InForcedColorsMode())
if (paint_info.phase == PaintPhase::kForcedColorsModeBackplate &&
layout_block.GetDocument().InForcedColorsMode()) {
PaintBackplate(line_boxes, paint_info, paint_offset);
return;
}
const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode();
......@@ -995,7 +1003,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
void NGBoxFragmentPainter::PaintBackplate(NGPaintFragment::ChildList line_boxes,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
if (paint_info.phase != PaintPhase::kForeground)
if (paint_info.phase != PaintPhase::kForcedColorsModeBackplate)
return;
// Only paint backplates behind text when forced-color-adjust is auto.
......
......@@ -114,6 +114,8 @@ void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info) {
PaintInfo info(paint_info);
info.phase = PaintPhase::kBlockBackground;
layout_object_.Paint(info);
info.phase = PaintPhase::kForcedColorsModeBackplate;
layout_object_.Paint(info);
info.phase = PaintPhase::kFloat;
layout_object_.Paint(info);
info.phase = PaintPhase::kForeground;
......
......@@ -776,6 +776,12 @@ void PaintLayerPainter::PaintForegroundForFragments(
local_painting_info, paint_flags);
}
if (RuntimeEnabledFeatures::ForcedColorsEnabled()) {
PaintForegroundForFragmentsWithPhase(
PaintPhase::kForcedColorsModeBackplate, layer_fragments, context,
local_painting_info, paint_flags);
}
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
paint_layer_.NeedsPaintPhaseFloat()) {
if (force_paint_chunks) {
......
......@@ -29,17 +29,22 @@
namespace blink {
// The painting of a layer occurs in 4 phases, Each involves a recursive
// The painting of a layer occurs in 5 phases, Each involves a recursive
// descent into the layer's layout objects in painting order:
// 1. Background phase: backgrounds and borders of all blocks are painted.
// Inlines are not painted at all. Touch-action hit test rects are also
// painted during this phase (see: paint/README.md#hit-test-painting).
// 2. Float phase: floating objects are painted above block backgrounds but
// 2. ForcedColorsModeBackplate phase: a readability backplate is painted
// behind all inline text, split by paragraph. This phase should only paint
// content when in forced colors mode to ensure readability for text above
// images.
// 3. Float phase: floating objects are painted above block backgrounds but
// entirely below inline content that can overlap them.
// 3. Foreground phase: all inlines are fully painted. Atomic inline elements
// will get all 4 phases invoked on them during this phase, as if they were
// stacking contexts (see ObjectPainter::paintAllPhasesAtomically()).
// 4. Outline phase: outlines are painted over the foreground.
// 4. Foreground phase: all inlines are fully painted. Atomic inline elements
// will get all 4 non-backplate phases invoked on them during this phase,
// as if they were stacking contexts (see
// ObjectPainter::paintAllPhasesAtomically()).
// 5. Outline phase: outlines are painted over the foreground.
enum class PaintPhase {
// Background phase
......@@ -60,6 +65,10 @@ enum class PaintPhase {
// to kBlockBackground.
kDescendantBlockBackgroundsOnly,
// ForcedColorsModeBackplate phase - used to ensure readability in forced
// colors mode.
kForcedColorsModeBackplate,
// Float phase
kFloat,
......
......@@ -198,6 +198,7 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info) {
bool ReplacedPainter::ShouldPaint(const ScopedPaintState& paint_state) const {
const auto& paint_info = paint_state.GetPaintInfo();
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kForcedColorsModeBackplate &&
!ShouldPaintSelfOutline(paint_info.phase) &&
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kMask &&
......
......@@ -14,6 +14,7 @@ namespace blink {
void SVGTextPainter::Paint(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kForcedColorsModeBackplate &&
paint_info.phase != PaintPhase::kSelection)
return;
......
......@@ -30,20 +30,22 @@ static WTF::String PaintPhaseAsDebugString(int paint_phase) {
case 2:
return "PaintPhaseDescendantBlockBackgroundsOnly";
case 3:
return "PaintPhaseFloat";
return "PaintPhaseForcedColorsModeBackplate";
case 4:
return "PaintPhaseForeground";
return "PaintPhaseFloat";
case 5:
return "PaintPhaseOutline";
return "PaintPhaseForeground";
case 6:
return "PaintPhaseSelfOutlineOnly";
return "PaintPhaseOutline";
case 7:
return "PaintPhaseDescendantOutlinesOnly";
return "PaintPhaseSelfOutlineOnly";
case 8:
return "PaintPhaseOverlayScrollbars";
return "PaintPhaseDescendantOutlinesOnly";
case 9:
return "PaintPhaseSelection";
return "PaintPhaseOverlayScrollbars";
case 10:
return "PaintPhaseSelection";
case 11:
return "PaintPhaseTextClip";
case DisplayItem::kPaintPhaseMax:
return "PaintPhaseMask";
......
......@@ -28,7 +28,7 @@ class PLATFORM_EXPORT DisplayItem {
public:
enum {
// Must be kept in sync with core/paint/PaintPhase.h.
kPaintPhaseMax = 11,
kPaintPhaseMax = 12,
};
// A display item type uniquely identifies a display item of a client.
......
......@@ -137,7 +137,7 @@ MATCHER_P5(IsPaintChunk, begin, end, id, properties, hit_test_data, "") {
// Shorter names for frequently used display item types in tests.
const DisplayItem::Type kBackgroundType = DisplayItem::kBoxDecorationBackground;
const DisplayItem::Type kForegroundType =
static_cast<DisplayItem::Type>(DisplayItem::kDrawingPaintPhaseFirst + 4);
static_cast<DisplayItem::Type>(DisplayItem::kDrawingPaintPhaseFirst + 5);
const DisplayItem::Type kDocumentBackgroundType =
DisplayItem::kDocumentBackground;
const DisplayItem::Type kScrollHitTestType = DisplayItem::kScrollHitTest;
......
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("../resources/test-image.jpg");
font-family: Ahem;
font-size: 20px;
forced-color-adjust: none; /* This turns the backplate feature off in forced colors mode.
The backplate is simulated in testing using a background-color
of Window behind the text.
*/
line-height: 20px;
text-align: justify;
width: 200px;
}
img {
float: left;
}
div {
background-color: Window;
}
</style>
</head>
<body>
<div>
<img src="../resources/float-image.jpg" style="width:50px;height:50px;">
In forced colors mode, the backplate for this paragraph should lie below the
the floating image.
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>
Forced colors mode - backplate.
Tests that backplate is not drawn above floats.
</title>
<link rel=match href=forced-colors-mode-backplate-09-expected.html>
<style>
body {
background-image: url("../resources/test-image.jpg");
font-family: Ahem;
font-size: 20px;
line-height: 20px;
text-align: justify;
width: 200px;
}
img {
float: left;
}
</style>
</head>
<body>
<div>
<img src="../resources/float-image.jpg" style="width:50px;height:50px;">
In forced colors mode, the backplate for this paragraph should lie below the
the floating image.
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("../resources/test-image.jpg");
font-family: Ahem;
font-size: 10px;
forced-color-adjust: none; /* This turns the backplate feature off in forced colors mode.
The backplate is simulated in testing using a background-color
of Window behind the text.
*/
line-height: 10px;
text-align: justify;
width: 100px;
}
div {
background-color: Window;
}
</style>
</head>
<body>
<div>
<div>
The two backplates should not overlap
</div>
<br>
<div style="margin-top: -25px; z-index: -1;">
in forced colors mode.
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>
Forced colors mode - backplate.
Tests that backplates of overlapping inline boxes do not overlap.
</title>
<link rel=match href=forced-colors-mode-backplate-10-expected.html>
<style>
body {
background-image: url("../resources/test-image.jpg");
font-family: Ahem;
font-size: 10px;
line-height: 10px;
text-align: justify;
width: 100px;
}
</style>
</head>
<body>
<div>
<div>
The two backplates should not overlap
</div>
<br>
<div style="margin-top: -25px; z-index: -1;">
in forced colors mode.
</div>
</div>
</body>
</html>
\ No newline at end of file
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