Delineate 'background-attachment: fixed' in BackgroundImageGeometry
Explicitly handle it within BackgroundImageGeometry::Calculate() now that said function is much smaller (and thus hopefully easier to follow) and more manageable. This allows seeing both the pre- and post- adjustments to the computed geometry in the same function. Fold UseFixedAttachment() and split some functions on BoxBackgroundPaintContext in support of this. Bug: 1500572 Change-Id: Ibe588d3b4373f07b21f1a136e55722c6d4fc8218 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5130060 Auto-Submit: Fredrik Söderquist <fs@opera.com> Commit-Queue: Stephen Chenney <schenney@chromium.org> Reviewed-by: Stephen Chenney <schenney@chromium.org> Cr-Commit-Position: refs/heads/main@{#1239137}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
9704615b00
commit
a79482acc0
third_party/blink/renderer/core/paint
@ -204,14 +204,6 @@ void BackgroundImageGeometry::SetSpaceY(LayoutUnit space,
|
||||
SetPhaseY(ComputeTilePhase(extra_offset, tile_size_.height + space));
|
||||
}
|
||||
|
||||
void BackgroundImageGeometry::UseFixedAttachment(
|
||||
const PhysicalOffset& attachment_point) {
|
||||
PhysicalOffset fixed_adjustment =
|
||||
attachment_point - unsnapped_dest_rect_.offset;
|
||||
fixed_adjustment.ClampNegativeToZero();
|
||||
phase_ += fixed_adjustment;
|
||||
}
|
||||
|
||||
SnappedAndUnsnappedOutsets BackgroundImageGeometry::ComputeDestRectAdjustments(
|
||||
const FillLayer& fill_layer,
|
||||
const BoxBackgroundPaintContext& paint_context,
|
||||
@ -340,76 +332,68 @@ BackgroundImageGeometry::ComputePositioningAreaAdjustments(
|
||||
void BackgroundImageGeometry::AdjustPositioningArea(
|
||||
const FillLayer& fill_layer,
|
||||
const BoxBackgroundPaintContext& paint_context,
|
||||
const PhysicalRect& paint_rect,
|
||||
const PaintInfo& paint_info,
|
||||
PhysicalRect& unsnapped_positioning_area,
|
||||
PhysicalRect& snapped_positioning_area,
|
||||
PhysicalOffset& unsnapped_box_offset,
|
||||
PhysicalOffset& snapped_box_offset) {
|
||||
if (paint_context.ShouldUseFixedAttachment(fill_layer)) {
|
||||
unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
|
||||
unsnapped_positioning_area;
|
||||
} else {
|
||||
unsnapped_dest_rect_ = paint_rect;
|
||||
// Attempt to shrink the destination rect if possible while also ensuring
|
||||
// that it paints to the border:
|
||||
//
|
||||
// * for background-clip content-box/padding-box, we can restrict to the
|
||||
// respective box, but for padding-box we also try to force alignment
|
||||
// with the inner border.
|
||||
//
|
||||
// * for border-box, we can modify individual edges iff the border fully
|
||||
// obscures the background.
|
||||
//
|
||||
// It is unsafe to derive dest from border information when any of the
|
||||
// following is true:
|
||||
// * the layer is not painted as part of a regular background phase
|
||||
// (e.g.paint_phase == kMask)
|
||||
// * non-SrcOver compositing is active
|
||||
// * painting_view_ is set, meaning we're dealing with a
|
||||
// LayoutView - for which dest rect is overflowing (expanded to cover
|
||||
// the whole canvas).
|
||||
// * We are painting table cells using the table background, or the table
|
||||
// has collapsed borders
|
||||
// * We are painting a block-fragmented box.
|
||||
// * There is a border image, because it may not be opaque or may be outset.
|
||||
bool disallow_border_derived_adjustment =
|
||||
!ShouldPaintSelfBlockBackground(paint_info.phase) ||
|
||||
fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
|
||||
paint_context.DisallowBorderDerivedAdjustment();
|
||||
|
||||
// Attempt to shrink the destination rect if possible while also ensuring
|
||||
// that it paints to the border:
|
||||
//
|
||||
// * for background-clip content-box/padding-box, we can restrict to the
|
||||
// respective box, but for padding-box we also try to force alignment
|
||||
// with the inner border.
|
||||
//
|
||||
// * for border-box, we can modify individual edges iff the border fully
|
||||
// obscures the background.
|
||||
//
|
||||
// It is unsafe to derive dest from border information when any of the
|
||||
// following is true:
|
||||
// * the layer is not painted as part of a regular background phase
|
||||
// (e.g.paint_phase == kMask)
|
||||
// * non-SrcOver compositing is active
|
||||
// * painting_view_ is set, meaning we're dealing with a
|
||||
// LayoutView - for which dest rect is overflowing (expanded to cover
|
||||
// the whole canvas).
|
||||
// * We are painting table cells using the table background, or the table
|
||||
// has collapsed borders
|
||||
// * We are painting a block-fragmented box.
|
||||
// * There is a border image, because it may not be opaque or may be outset.
|
||||
bool disallow_border_derived_adjustment =
|
||||
!ShouldPaintSelfBlockBackground(paint_info.phase) ||
|
||||
fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
|
||||
paint_context.DisallowBorderDerivedAdjustment();
|
||||
// Compute all the outsets we need to apply to the rectangles. These
|
||||
// outsets also include the snapping behavior.
|
||||
const SnappedAndUnsnappedOutsets dest_adjust = ComputeDestRectAdjustments(
|
||||
fill_layer, paint_context, unsnapped_positioning_area,
|
||||
disallow_border_derived_adjustment);
|
||||
const SnappedAndUnsnappedOutsets box_outset =
|
||||
ComputePositioningAreaAdjustments(fill_layer, paint_context,
|
||||
unsnapped_positioning_area,
|
||||
disallow_border_derived_adjustment);
|
||||
|
||||
// Compute all the outsets we need to apply to the rectangles. These
|
||||
// outsets also include the snapping behavior.
|
||||
const SnappedAndUnsnappedOutsets dest_adjust = ComputeDestRectAdjustments(
|
||||
fill_layer, paint_context, unsnapped_positioning_area,
|
||||
disallow_border_derived_adjustment);
|
||||
const SnappedAndUnsnappedOutsets box_outset =
|
||||
ComputePositioningAreaAdjustments(fill_layer, paint_context,
|
||||
unsnapped_positioning_area,
|
||||
disallow_border_derived_adjustment);
|
||||
// Offset of the positioning area from the corner of positioning_box_.
|
||||
unsnapped_box_offset =
|
||||
box_outset.unsnapped.Offset() - dest_adjust.unsnapped.Offset();
|
||||
snapped_box_offset =
|
||||
box_outset.snapped.Offset() - dest_adjust.snapped.Offset();
|
||||
|
||||
// Offset of the positioning area from the corner of positioning_box_.
|
||||
unsnapped_box_offset =
|
||||
box_outset.unsnapped.Offset() - dest_adjust.unsnapped.Offset();
|
||||
snapped_box_offset =
|
||||
box_outset.snapped.Offset() - dest_adjust.snapped.Offset();
|
||||
|
||||
// Apply the adjustments.
|
||||
snapped_dest_rect_ = unsnapped_dest_rect_;
|
||||
snapped_dest_rect_.Contract(dest_adjust.snapped);
|
||||
snapped_dest_rect_ = PhysicalRect(ToPixelSnappedRect(snapped_dest_rect_));
|
||||
snapped_dest_rect_.size.ClampNegativeToZero();
|
||||
unsnapped_dest_rect_.Contract(dest_adjust.unsnapped);
|
||||
unsnapped_dest_rect_.size.ClampNegativeToZero();
|
||||
snapped_positioning_area = unsnapped_positioning_area;
|
||||
snapped_positioning_area.Contract(box_outset.snapped);
|
||||
snapped_positioning_area =
|
||||
PhysicalRect(ToPixelSnappedRect(snapped_positioning_area));
|
||||
snapped_positioning_area.size.ClampNegativeToZero();
|
||||
unsnapped_positioning_area.Contract(box_outset.unsnapped);
|
||||
unsnapped_positioning_area.size.ClampNegativeToZero();
|
||||
}
|
||||
// Apply the adjustments.
|
||||
snapped_dest_rect_ = unsnapped_dest_rect_;
|
||||
snapped_dest_rect_.Contract(dest_adjust.snapped);
|
||||
snapped_dest_rect_ = PhysicalRect(ToPixelSnappedRect(snapped_dest_rect_));
|
||||
snapped_dest_rect_.size.ClampNegativeToZero();
|
||||
unsnapped_dest_rect_.Contract(dest_adjust.unsnapped);
|
||||
unsnapped_dest_rect_.size.ClampNegativeToZero();
|
||||
snapped_positioning_area = unsnapped_positioning_area;
|
||||
snapped_positioning_area.Contract(box_outset.snapped);
|
||||
snapped_positioning_area =
|
||||
PhysicalRect(ToPixelSnappedRect(snapped_positioning_area));
|
||||
snapped_positioning_area.size.ClampNegativeToZero();
|
||||
unsnapped_positioning_area.Contract(box_outset.unsnapped);
|
||||
unsnapped_positioning_area.size.ClampNegativeToZero();
|
||||
}
|
||||
|
||||
void BackgroundImageGeometry::CalculateFillTileSize(
|
||||
@ -659,8 +643,7 @@ void BackgroundImageGeometry::Calculate(
|
||||
// Unsnapped positioning area is used to derive quantities
|
||||
// that reference source image maps and define non-integer values, such
|
||||
// as phase and position.
|
||||
PhysicalRect unsnapped_positioning_area =
|
||||
paint_context.ComputePositioningArea(paint_info, fill_layer, paint_rect);
|
||||
PhysicalRect unsnapped_positioning_area;
|
||||
|
||||
// Snapped positioning area is used for sizing images based on the
|
||||
// background area (like cover and contain), and for setting the repeat
|
||||
@ -671,10 +654,22 @@ void BackgroundImageGeometry::Calculate(
|
||||
PhysicalOffset unsnapped_box_offset;
|
||||
PhysicalOffset snapped_box_offset;
|
||||
|
||||
// This method also sets the destination rects.
|
||||
AdjustPositioningArea(fill_layer, paint_context, paint_rect, paint_info,
|
||||
unsnapped_positioning_area, snapped_positioning_area,
|
||||
unsnapped_box_offset, snapped_box_offset);
|
||||
if (paint_context.ShouldUseFixedAttachment(fill_layer)) {
|
||||
unsnapped_positioning_area =
|
||||
paint_context.FixedAttachmentPositioningArea(paint_info);
|
||||
unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
|
||||
unsnapped_positioning_area;
|
||||
} else {
|
||||
unsnapped_positioning_area =
|
||||
paint_context.NormalPositioningArea(paint_rect);
|
||||
unsnapped_dest_rect_ = paint_rect;
|
||||
|
||||
// This method adjusts `unsnapped_dest_rect_` and sets
|
||||
// `snapped_dest_rect_`.
|
||||
AdjustPositioningArea(fill_layer, paint_context, paint_info,
|
||||
unsnapped_positioning_area, snapped_positioning_area,
|
||||
unsnapped_box_offset, snapped_box_offset);
|
||||
}
|
||||
|
||||
// Sets the tile_size_.
|
||||
CalculateFillTileSize(fill_layer, paint_context.Style(),
|
||||
@ -689,7 +684,10 @@ void BackgroundImageGeometry::Calculate(
|
||||
snapped_positioning_area.size, unsnapped_box_offset, snapped_box_offset);
|
||||
|
||||
if (paint_context.ShouldUseFixedAttachment(fill_layer)) {
|
||||
UseFixedAttachment(paint_rect.offset);
|
||||
PhysicalOffset fixed_adjustment =
|
||||
paint_rect.offset - unsnapped_dest_rect_.offset;
|
||||
fixed_adjustment.ClampNegativeToZero();
|
||||
phase_ += fixed_adjustment;
|
||||
}
|
||||
|
||||
// The actual painting area can be bigger than the provided background
|
||||
|
@ -79,8 +79,6 @@ class BackgroundImageGeometry {
|
||||
void SetSpaceX(LayoutUnit space, LayoutUnit extra_offset);
|
||||
void SetSpaceY(LayoutUnit space, LayoutUnit extra_offset);
|
||||
|
||||
void UseFixedAttachment(const PhysicalOffset& attachment_point);
|
||||
|
||||
// Compute adjustments for the destination rects. Adjustments
|
||||
// both optimize painting when the background is obscured by a
|
||||
// border, and snap the dest rect to the border. They also
|
||||
@ -109,7 +107,6 @@ class BackgroundImageGeometry {
|
||||
|
||||
void AdjustPositioningArea(const FillLayer&,
|
||||
const BoxBackgroundPaintContext&,
|
||||
const PhysicalRect&,
|
||||
const PaintInfo&,
|
||||
PhysicalRect&,
|
||||
PhysicalRect&,
|
||||
|
@ -208,6 +208,11 @@ PhysicalRect BoxBackgroundPaintContext::ComputePositioningArea(
|
||||
if (ShouldUseFixedAttachment(fill_layer)) {
|
||||
return FixedAttachmentPositioningArea(paint_info);
|
||||
}
|
||||
return NormalPositioningArea(paint_rect);
|
||||
}
|
||||
|
||||
PhysicalRect BoxBackgroundPaintContext::NormalPositioningArea(
|
||||
const PhysicalRect& paint_rect) const {
|
||||
if (painting_view_ || cell_using_container_background_ ||
|
||||
box_has_multiple_fragments_) {
|
||||
return {PhysicalOffset(), positioning_size_override_};
|
||||
|
@ -50,9 +50,14 @@ class BoxBackgroundPaintContext {
|
||||
|
||||
// Compute the initial position area based on the geometry for the object
|
||||
// this BackgroundPaintContext was created for.
|
||||
PhysicalRect NormalPositioningArea(const PhysicalRect& paint_rect) const;
|
||||
// As above, but also considers background-attachment: fixed.
|
||||
PhysicalRect ComputePositioningArea(const PaintInfo& paint_info,
|
||||
const FillLayer& fill_layer,
|
||||
const PhysicalRect& paint_rect) const;
|
||||
// The positioning area for a background layer with background-attachment:
|
||||
// fixed.
|
||||
PhysicalRect FixedAttachmentPositioningArea(const PaintInfo&) const;
|
||||
|
||||
PhysicalBoxStrut BorderOutsets() const;
|
||||
PhysicalBoxStrut PaddingOutsets() const;
|
||||
@ -89,8 +94,6 @@ class BoxBackgroundPaintContext {
|
||||
BoxBackgroundPaintContext(const LayoutBoxModelObject* box,
|
||||
const LayoutBoxModelObject* positioning_box);
|
||||
|
||||
PhysicalRect FixedAttachmentPositioningArea(const PaintInfo&) const;
|
||||
|
||||
// In most cases this is the same as positioning_box_. They are different
|
||||
// when we are painting:
|
||||
// 1. the view background (box_ is the LayoutView, and positioning_box_ is
|
||||
|
Reference in New Issue
Block a user