Commit ea980c90 authored by Alison Maher's avatar Alison Maher Committed by Commit Bot

Forced colors mode backplate (non-LayoutNG)

This change adds logic for painting a readability backplate behind
text in forced colors mode for non-LayoutNG. Backplates are split by
paragraph, as defined by two consecutive line breaks. A backplate is
not drawn if forced-color-adjust is none.

Tests are added for this in the LayoutNG change:
https://chromium-review.googlesource.com/c/chromium/src/+/1749299

Bug: 970285
Change-Id: I51aec229d905de5fe7b233792c41555037c5b172
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1713333
Commit-Queue: Alison Maher <almaher@microsoft.com>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarKevin Babbitt <kbabbitt@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#691937}
parent 95af4312
......@@ -270,8 +270,11 @@ void BlockPainter::PaintBlockFlowContents(const PaintInfo& paint_info,
} else if (ShouldPaintDescendantOutlines(paint_info.phase)) {
ObjectPainter(layout_block_).PaintInlineChildrenOutlines(paint_info);
} else {
LineBoxListPainter(To<LayoutBlockFlow>(layout_block_).LineBoxes())
.Paint(layout_block_, paint_info, paint_offset);
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);
}
// If we don't have any floats to paint, or we're in the wrong paint phase,
......
......@@ -5,17 +5,77 @@
#include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_box_model.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/line/inline_flow_box.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/line/line_box_list.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.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_timing_detector.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
namespace {
// Recursively build up backplates behind inline text boxes, each split at the
// paragraph level. Store the results in paragraph_backplates.
void BuildBackplate(const InlineFlowBox* box,
const PhysicalOffset& paint_offset,
PhysicalRect* current_backplate,
int* consecutive_line_breaks,
Vector<PhysicalRect>* paragraph_backplates) {
DCHECK(current_backplate && consecutive_line_breaks && paragraph_backplates);
// The number of consecutive forced breaks that split the backplate by
// paragraph.
static constexpr int kMaxConsecutiveLineBreaks = 2;
// Build up and paint backplates of all child inline text boxes. We are not
// able to simply use the linebox rect to compute the backplate because the
// backplate should only be painted for inline text and not for atomic
// inlines.
for (InlineBox* child = box->FirstChild(); child;
child = child->NextOnLine()) {
LineLayoutItem layout_item = child->GetLineLayoutItem();
if (layout_item.IsText() || layout_item.IsListMarker()) {
if (layout_item.IsText()) {
String child_text =
ToInlineTextBox(child)->GetLineLayoutItem().GetText();
if (ToInlineTextBox(child)->IsLineBreak() ||
child_text.StartsWith('\n'))
(*consecutive_line_breaks)++;
}
if (*consecutive_line_breaks >= kMaxConsecutiveLineBreaks) {
// This is a paragraph point.
paragraph_backplates->push_back(*current_backplate);
*current_backplate = PhysicalRect();
*consecutive_line_breaks = 0;
}
PhysicalOffset box_origin(PhysicalOffset(child->Location()) +
paint_offset);
PhysicalRect box_rect(box_origin, PhysicalSize(child->LogicalWidth(),
child->LogicalHeight()));
if (*consecutive_line_breaks > 0 && !box_rect.IsEmpty()) {
// Text was reached, so reset consecutive_line_breaks.
*consecutive_line_breaks = 0;
}
current_backplate->Unite(box_rect);
} else if (child->IsInlineFlowBox()) {
// If an inline flow box was reached, continue to recursively build up the
// backplate.
BuildBackplate(ToInlineFlowBox(child), paint_offset, current_backplate,
consecutive_line_breaks, paragraph_backplates);
}
}
}
} // anonymous namespace
static void AddPDFURLRectsForInlineChildrenRecursively(
const LayoutObject& layout_object,
const PaintInfo& paint_info,
......@@ -31,7 +91,7 @@ static void AddPDFURLRectsForInlineChildrenRecursively(
}
}
void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
DCHECK(!ShouldPaintSelfOutline(paint_info.phase) &&
......@@ -42,7 +102,7 @@ void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kTextClip &&
paint_info.phase != PaintPhase::kMask)
return;
return false;
// The only way an inline could paint like this is if it has a layer.
DCHECK(layout_object.IsLayoutBlock() ||
......@@ -54,11 +114,20 @@ void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
// If we have no lines then we have no work to do.
if (!line_box_list_.First())
return;
return false;
if (!line_box_list_.AnyLineIntersectsRect(
LineLayoutBoxModel(const_cast<LayoutBoxModelObject*>(&layout_object)),
paint_info.GetCullRect(), paint_offset))
return false;
return true;
}
void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
if (!ShouldPaint(layout_object, paint_info, paint_offset))
return;
ScopedPaintTimingDetectorBlockPaintHook
......@@ -88,4 +157,45 @@ void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
}
}
void LineBoxListPainter::PaintBackplate(
const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const {
if (!ShouldPaint(layout_object, paint_info, paint_offset))
return;
// Only paint backplates behind text when forced-color-adjust is auto.
const ComputedStyle& style =
line_box_list_.First()->GetLineLayoutItem().StyleRef();
if (style.ForcedColorAdjust() == EForcedColorAdjust::kNone)
return;
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, layout_object,
DisplayItem::kForcedColorsModeBackplate))
return;
DrawingRecorder recorder(paint_info.context, layout_object,
DisplayItem::kForcedColorsModeBackplate);
Color backplate_color = style.ForcedBackplateColor();
const auto& backplates = GetBackplates(paint_offset);
for (const auto backplate : backplates)
paint_info.context.FillRect(FloatRect(backplate), backplate_color);
}
Vector<PhysicalRect> LineBoxListPainter::GetBackplates(
const PhysicalOffset& paint_offset) const {
Vector<PhysicalRect> paragraph_backplates;
PhysicalRect current_backplate;
int consecutive_line_breaks = 0;
for (const InlineFlowBox* line : line_box_list_) {
// Recursively build up and paint backplates for line boxes containing text.
BuildBackplate(line, paint_offset, &current_backplate,
&consecutive_line_breaks, &paragraph_backplates);
}
if (!current_backplate.IsEmpty())
paragraph_backplates.push_back(current_backplate);
return paragraph_backplates;
}
} // namespace blink
......@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
......@@ -14,6 +15,7 @@ class LayoutBoxModelObject;
class LineBoxList;
struct PaintInfo;
struct PhysicalOffset;
struct PhysicalRect;
class LineBoxListPainter {
STACK_ALLOCATED();
......@@ -25,9 +27,20 @@ class LineBoxListPainter {
void Paint(const LayoutBoxModelObject&,
const PaintInfo&,
const PhysicalOffset& paint_offset) const;
void PaintBackplate(const LayoutBoxModelObject& layout_object,
const PaintInfo&,
const PhysicalOffset& paint_offset) const;
private:
const LineBoxList& line_box_list_;
bool ShouldPaint(const LayoutBoxModelObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) const;
// Returns a vector of backplates that surround the paragraphs of text within
// line_box_list_.
Vector<PhysicalRect> GetBackplates(const PhysicalOffset& paint_offset) const;
};
} // namespace blink
......
......@@ -304,9 +304,6 @@ crbug.com/591099 fast/css/forced-colors-mode/forced-colors-mode-15.html [ Failur
crbug.com/591099 virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-14.html [ Failure ]
crbug.com/591099 virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-15.html [ Failure ]
# Backplate tests should not be run when LayoutNG is disabled until it is implemented there.
crbug.com/970285 virtual/forced-colors/fast/css/forced-colors-mode/backplate [ Skip ]
### http/tests/credentialmanager/
crbug.com/874695 http/tests/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html [ Failure ]
......
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