/*
 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights
 * reserved.
 *
 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
 *
 * Other contributors:
 *   Robert O'Callahan <roc+@cs.cmu.edu>
 *   David Baron <dbaron@fas.harvard.edu>
 *   Christian Biesinger <cbiesinger@web.de>
 *   Randall Jesup <rjesup@wgate.com>
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 *   Josh Soref <timeless@mac.com>
 *   Boris Zbarsky <bzbarsky@mit.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * Alternatively, the contents of this file may be used under the terms
 * of either the Mozilla Public License Version 1.1, found at
 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
 * (the "GPL"), in which case the provisions of the MPL or the GPL are
 * applicable instead of those above.  If you wish to allow use of your
 * version of this file only under the terms of one of those two
 * licenses (the MPL or the GPL) and not to allow others to use your
 * version of this file under the LGPL, indicate your decision by
 * deletingthe provisions above and replace them with the notice and
 * other provisions required by the MPL or the GPL, as the case may be.
 * If you do not delete the provisions above, a recipient may use your
 * version of this file under any of the LGPL, the MPL or the GPL.
 */

#include "third_party/blink/renderer/core/paint/paint_layer.h"

#include <limits>

#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/pseudo_style_request.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h"
#include "third_party/blink/renderer/core/layout/hit_test_request.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/hit_testing_transform_state.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
#include "third_party/blink/renderer/core/paint/box_reflection_utils.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/filters/filter.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"

namespace blink {

namespace {

static CompositingQueryMode g_compositing_query_mode =
    kCompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;

#ifdef OS_LINUX
struct SameSizeAsPaintLayer : DisplayItemClient {
  // The bit fields may fit into the machine word of DisplayItemClient which
  // has only 8-bit data.
  unsigned bit_fields1 : 24;
  unsigned bit_fields2;
  void* pointers[11];
#if DCHECK_IS_ON()
  void* pointer;
#endif
  LayoutUnit layout_units[4];
  IntSize size;
  Persistent<PaintLayerScrollableArea> scrollable_area;
  CullRect previous_cull_rect;
};

static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer),
              "PaintLayer should stay small");
#endif

}  // namespace

PaintLayerRareData::PaintLayerRareData()
    : enclosing_pagination_layer(nullptr),
      potential_compositing_reasons_from_style(CompositingReason::kNone),
      potential_compositing_reasons_from_non_style(CompositingReason::kNone),
      compositing_reasons(CompositingReason::kNone),
      squashing_disallowed_reasons(SquashingDisallowedReason::kNone),
      grouped_mapping(nullptr) {}

PaintLayerRareData::~PaintLayerRareData() = default;

PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
    : is_root_layer_(layout_object.IsLayoutView()),
      has_visible_content_(false),
      needs_descendant_dependent_flags_update_(true),
      needs_visual_overflow_recalc_(true),
      has_visible_descendant_(false),
#if DCHECK_IS_ON()
      // The root layer (LayoutView) does not need position update at start
      // because its Location() is always 0.
      needs_position_update_(!IsRootLayer()),
#endif
      has3d_transformed_descendant_(false),
      contains_dirty_overlay_scrollbars_(false),
      needs_ancestor_dependent_compositing_inputs_update_(
          !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
      child_needs_compositing_inputs_update_(
          !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
      has_compositing_descendant_(false),
      should_isolate_composited_descendants_(false),
      lost_grouped_mapping_(false),
      needs_repaint_(false),
      previous_paint_result_(kFullyPainted),
      needs_paint_phase_descendant_outlines_(false),
      needs_paint_phase_float_(false),
      needs_paint_phase_descendant_block_backgrounds_(false),
      has_descendant_with_clip_path_(false),
      has_non_isolated_descendant_with_blend_mode_(false),
      has_fixed_position_descendant_(false),
      has_sticky_position_descendant_(false),
      has_non_contained_absolute_position_descendant_(false),
      self_painting_status_changed_(false),
      filter_on_effect_node_dirty_(false),
      is_under_svg_hidden_container_(false),
      descendant_has_direct_or_scrolling_compositing_reason_(false),
      needs_compositing_reasons_update_(
          !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()),
      descendant_may_need_compositing_requirements_update_(false),
      needs_compositing_layer_assignment_(false),
      descendant_needs_compositing_layer_assignment_(false),
      has_self_painting_layer_descendant_(false),
      is_non_stacked_with_in_flow_stacked_descendant_(false),
      layout_object_(layout_object),
      parent_(nullptr),
      previous_(nullptr),
      next_(nullptr),
      first_(nullptr),
      last_(nullptr),
      static_inline_position_(0),
      static_block_position_(0),
      ancestor_overflow_layer_(nullptr)
#if DCHECK_IS_ON()
      ,
      stacking_parent_(nullptr)
#endif
{
  is_self_painting_layer_ = ShouldBeSelfPaintingLayer();

  UpdateScrollableArea();
}

PaintLayer::~PaintLayer() {
  if (rare_data_ && rare_data_->resource_info) {
    const ComputedStyle& style = GetLayoutObject().StyleRef();
    if (style.HasFilter())
      style.Filter().RemoveClient(*rare_data_->resource_info);
    if (auto* reference_clip =
            ToReferenceClipPathOperationOrNull(style.ClipPath()))
      reference_clip->RemoveClient(*rare_data_->resource_info);
    rare_data_->resource_info->ClearLayer();
  }
  if (GetLayoutObject().GetFrame()) {
    if (ScrollingCoordinator* scrolling_coordinator = GetScrollingCoordinator())
      scrolling_coordinator->WillDestroyLayer(this);
  }

  if (GroupedMapping()) {
    DisableCompositingQueryAsserts disabler;
    SetGroupedMapping(nullptr, kInvalidateLayerAndRemoveFromMapping);
  }

  // Child layers will be deleted by their corresponding layout objects, so
  // we don't need to delete them ourselves.

  ClearCompositedLayerMapping(true);

  if (scrollable_area_)
    scrollable_area_->Dispose();

#if DCHECK_IS_ON()
  // stacking_parent_ should be cleared because DirtyStackingContextZOrderLists
  // should have been called.
  if (!GetLayoutObject().DocumentBeingDestroyed())
    DCHECK(!stacking_parent_);
#endif
}

String PaintLayer::DebugName() const {
  return GetLayoutObject().DebugName();
}

DOMNodeId PaintLayer::OwnerNodeId() const {
  return static_cast<const DisplayItemClient&>(GetLayoutObject()).OwnerNodeId();
}

LayoutRect PaintLayer::VisualRect() const {
  return layout_object_.FragmentsVisualRectBoundingBox();
}

PaintLayerCompositor* PaintLayer::Compositor() const {
  if (!GetLayoutObject().View())
    return nullptr;
  return GetLayoutObject().View()->Compositor();
}

void PaintLayer::ContentChanged(ContentChangeType change_type) {
  // updateLayerCompositingState will query compositingReasons for accelerated
  // overflow scrolling.  This is tripped by
  // web_tests/compositing/content-changed-chicken-egg.html
  DisableCompositingQueryAsserts disabler;

  if (Compositor()) {
    if (change_type == kCanvasChanged)
      SetNeedsCompositingInputsUpdate();

    if (change_type == kCanvasContextChanged) {
      SetNeedsCompositingInputsUpdate();

      // Although we're missing test coverage, we need to call
      // GraphicsLayer::SetContentsToCcLayer with the new cc::Layer for this
      // canvas. See http://crbug.com/349195
      if (HasCompositedLayerMapping()) {
        GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
            kGraphicsLayerUpdateSubtree);
      }
    }
  }

  if (CompositedLayerMapping* composited_layer_mapping =
          GetCompositedLayerMapping())
    composited_layer_mapping->ContentChanged(change_type);
}

bool PaintLayer::PaintsWithFilters() const {
  if (!GetLayoutObject().HasFilterInducingProperty())
    return false;

  // https://code.google.com/p/chromium/issues/detail?id=343759
  DisableCompositingQueryAsserts disabler;
  return !GetCompositedLayerMapping() ||
         GetCompositingState() != kPaintsIntoOwnBacking;
}


LayoutSize PaintLayer::SubpixelAccumulation() const {
  return rare_data_ ? rare_data_->subpixel_accumulation : LayoutSize();
}

void PaintLayer::SetSubpixelAccumulation(const LayoutSize& size) {
  if (rare_data_ || !size.IsZero()) {
    EnsureRareData().subpixel_accumulation = size;
    if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
      scrollable_area->PositionOverflowControls();
    }
  }
}

void PaintLayer::UpdateLayerPositionsAfterLayout() {
  TRACE_EVENT0("blink,benchmark",
               "PaintLayer::updateLayerPositionsAfterLayout");
  RUNTIME_CALL_TIMER_SCOPE(
      V8PerIsolateData::MainThreadIsolate(),
      RuntimeCallStats::CounterId::kUpdateLayerPositionsAfterLayout);

  ClearClipRects();
  UpdateLayerPositionRecursive();

  {
    // FIXME: Remove incremental compositing updates after fixing the
    // chicken/egg issues, https://crbug.com/343756
    DisableCompositingQueryAsserts disabler;
    UpdatePaginationRecursive(EnclosingPaginationLayer());
  }
}

void PaintLayer::UpdateLayerPositionRecursive(
    UpdateLayerPositionBehavior behavior,
    bool dirty_compositing_if_needed) {
  LayoutPoint old_location = location_;
  switch (behavior) {
    case AllLayers:
      UpdateLayerPosition();
      break;
    case OnlyStickyLayers:
      if (GetLayoutObject().StyleRef().HasStickyConstrainedPosition())
        UpdateLayerPosition();
      if (PaintLayerScrollableArea* scroller = GetScrollableArea()) {
        if (!scroller->HasStickyDescendants())
          return;
      }
      break;
    default:
      NOTREACHED();
  }

  if (dirty_compositing_if_needed && location_ != old_location)
    SetNeedsCompositingInputsUpdate();

  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
    child->UpdateLayerPositionRecursive(behavior, dirty_compositing_if_needed);
}

bool PaintLayer::SticksToScroller() const {
  if (!GetLayoutObject().StyleRef().HasStickyConstrainedPosition())
    return false;
  return AncestorOverflowLayer()->GetScrollableArea();
}

bool PaintLayer::FixedToViewport() const {
  if (GetLayoutObject().StyleRef().GetPosition() != EPosition::kFixed)
    return false;
  return GetLayoutObject().Container() == GetLayoutObject().View();
}

bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const {
  if (FixedToViewport() != other->FixedToViewport())
    return true;
  // If either element sticks we cannot trivially determine that the layers do
  // not scroll with respect to each other.
  if (SticksToScroller() || other->SticksToScroller())
    return true;
  return AncestorScrollingLayer() != other->AncestorScrollingLayer();
}

bool PaintLayer::IsAffectedByScrollOf(const PaintLayer* ancestor) const {
  if (this == ancestor)
    return false;

  const PaintLayer* current_layer = this;
  while (current_layer && current_layer != ancestor) {
    bool ancestor_escaped = false;
    const PaintLayer* container =
        current_layer->ContainingLayer(ancestor, &ancestor_escaped);
    if (ancestor_escaped)
      return false;
    // Workaround the bug that LayoutView is mistakenly considered
    // a fixed-pos container.
    if (current_layer->GetLayoutObject().IsFixedPositioned() &&
        container->IsRootLayer())
      return false;
    current_layer = container;
  }
  return current_layer == ancestor;
}

void PaintLayer::UpdateLayerPositionsAfterOverflowScroll() {
  if (IsRootLayer()) {
    // The root PaintLayer (i.e. the LayoutView) is special, in that scroll
    // offset is not included in clip rects. Therefore, we do not need to clear
    // them when that PaintLayer is scrolled. We also don't need to update layer
    // positions, because they also do not depend on the root's scroll offset.
    if (GetScrollableArea()->HasStickyDescendants()) {
      UpdateLayerPositionRecursive(OnlyStickyLayers,
                                   /* dirty_compositing */ false);
    }
    return;
  }
  ClearClipRects();
  UpdateLayerPositionRecursive(AllLayers, /* dirty_compositing */ false);
}

void PaintLayer::UpdateTransformationMatrix() {
  if (TransformationMatrix* transform = Transform()) {
    LayoutBox* box = GetLayoutBox();
    DCHECK(box);
    transform->MakeIdentity();
    box->StyleRef().ApplyTransform(
        *transform, box->Size(), ComputedStyle::kIncludeTransformOrigin,
        ComputedStyle::kIncludeMotionPath,
        ComputedStyle::kIncludeIndependentTransformProperties);
    MakeMatrixRenderable(
        *transform,
        Compositor() ? Compositor()->HasAcceleratedCompositing() : false);
  }
}

void PaintLayer::UpdateTransform(const ComputedStyle* old_style,
                                 const ComputedStyle& new_style) {
  // It's possible for the old and new style transform data to be equivalent
  // while hasTransform() differs, as it checks a number of conditions aside
  // from just the matrix, including but not limited to animation state.
  if (old_style && old_style->HasTransform() == new_style.HasTransform() &&
      new_style.TransformDataEquivalent(*old_style)) {
    return;
  }

  // LayoutObject::HasTransformRelatedProperty is also true when there is
  // transform-style: preserve-3d or perspective set, so check style too.
  bool has_transform = GetLayoutObject().HasTransformRelatedProperty() &&
                       new_style.HasTransform();
  bool had3d_transform = Has3DTransform();

  bool had_transform = Transform();
  if (has_transform != had_transform) {
    if (has_transform)
      EnsureRareData().transform = TransformationMatrix::Create();
    else
      rare_data_->transform.reset();

    // PaintLayers with transforms act as clip rects roots, so clear the cached
    // clip rects here.
    ClearClipRects();
  } else if (has_transform) {
    ClearClipRects(kAbsoluteClipRectsIgnoringViewportClip);
  }

  UpdateTransformationMatrix();

  if (had3d_transform != Has3DTransform()) {
    SetNeedsCompositingInputsUpdateInternal();
    MarkAncestorChainForFlagsUpdate();
  }

  if (LocalFrameView* frame_view = GetLayoutObject().GetDocument().View())
    frame_view->SetNeedsUpdateGeometries();
}

static PaintLayer* EnclosingLayerForContainingBlock(PaintLayer* layer) {
  if (LayoutObject* containing_block =
          layer->GetLayoutObject().ContainingBlock())
    return containing_block->EnclosingLayer();
  return nullptr;
}

static const PaintLayer* EnclosingLayerForContainingBlock(
    const PaintLayer* layer) {
  if (const LayoutObject* containing_block =
          layer->GetLayoutObject().ContainingBlock())
    return containing_block->EnclosingLayer();
  return nullptr;
}

PaintLayer* PaintLayer::RenderingContextRoot() {
  PaintLayer* rendering_context = nullptr;

  if (ShouldPreserve3D())
    rendering_context = this;

  for (PaintLayer* current = EnclosingLayerForContainingBlock(this);
       current && current->ShouldPreserve3D();
       current = EnclosingLayerForContainingBlock(current))
    rendering_context = current;

  return rendering_context;
}

const PaintLayer* PaintLayer::RenderingContextRoot() const {
  const PaintLayer* rendering_context = nullptr;

  if (ShouldPreserve3D())
    rendering_context = this;

  for (const PaintLayer* current = EnclosingLayerForContainingBlock(this);
       current && current->ShouldPreserve3D();
       current = EnclosingLayerForContainingBlock(current))
    rendering_context = current;

  return rendering_context;
}

TransformationMatrix PaintLayer::CurrentTransform() const {
  if (TransformationMatrix* transform = Transform())
    return *transform;
  return TransformationMatrix();
}

TransformationMatrix PaintLayer::RenderableTransform(
    GlobalPaintFlags global_paint_flags) const {
  TransformationMatrix* transform = Transform();
  if (!transform)
    return TransformationMatrix();

  if (global_paint_flags & kGlobalPaintFlattenCompositingLayers) {
    TransformationMatrix matrix = *transform;
    MakeMatrixRenderable(matrix, false /* flatten 3d */);
    return matrix;
  }

  return *transform;
}

void PaintLayer::ConvertFromFlowThreadToVisualBoundingBoxInAncestor(
    const PaintLayer* ancestor_layer,
    LayoutRect& rect) const {
  PaintLayer* pagination_layer = EnclosingPaginationLayer();
  DCHECK(pagination_layer);
  LayoutFlowThread& flow_thread =
      ToLayoutFlowThread(pagination_layer->GetLayoutObject());

  // First make the flow thread rectangle relative to the flow thread, not to
  // |layer|.
  LayoutPoint offset_within_pagination_layer;
  ConvertToLayerCoords(pagination_layer, offset_within_pagination_layer);
  rect.MoveBy(offset_within_pagination_layer);

  // Then make the rectangle visual, relative to the fragmentation context.
  // Split our box up into the actual fragment boxes that layout in the
  // columns/pages and unite those together to get our true bounding box.
  rect = flow_thread.FragmentsBoundingBox(rect);

  // Finally, make the visual rectangle relative to |ancestorLayer|.
  if (ancestor_layer->EnclosingPaginationLayer() != pagination_layer) {
    rect.MoveBy(pagination_layer->VisualOffsetFromAncestor(ancestor_layer));
    return;
  }
  // The ancestor layer is inside the same pagination layer as |layer|, so we
  // need to subtract the visual distance from the ancestor layer to the
  // pagination layer.
  rect.MoveBy(-ancestor_layer->VisualOffsetFromAncestor(pagination_layer));
}

void PaintLayer::UpdatePaginationRecursive(bool needs_pagination_update) {
  if (rare_data_)
    rare_data_->enclosing_pagination_layer = nullptr;

  if (GetLayoutObject().IsLayoutFlowThread())
    needs_pagination_update = true;

  if (needs_pagination_update) {
    // Each paginated layer has to paint on its own. There is no recurring into
    // child layers. Each layer has to be checked individually and genuinely
    // know if it is going to have to split itself up when painting only its
    // contents (and not any other descendant layers). We track an
    // enclosingPaginationLayer instead of using a simple bit, since we want to
    // be able to get back to that layer easily.
    if (LayoutFlowThread* containing_flow_thread =
            GetLayoutObject().FlowThreadContainingBlock())
      EnsureRareData().enclosing_pagination_layer =
          containing_flow_thread->Layer();
  }

  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
    child->UpdatePaginationRecursive(needs_pagination_update);
}

void PaintLayer::ClearPaginationRecursive() {
  if (rare_data_)
    rare_data_->enclosing_pagination_layer = nullptr;
  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
    child->ClearPaginationRecursive();
}

const PaintLayer& PaintLayer::TransformAncestorOrRoot() const {
  return TransformAncestor() ? *TransformAncestor()
                             : *GetLayoutObject().View()->Layer();
}

void PaintLayer::MapPointInPaintInvalidationContainerToBacking(
    const LayoutBoxModelObject& paint_invalidation_container,
    FloatPoint& point) {
  PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer();
  if (!paint_invalidation_layer->GroupedMapping())
    return;

  GraphicsLayer* squashing_layer =
      paint_invalidation_layer->GroupedMapping()->SquashingLayer();

  PropertyTreeState source_state =
      paint_invalidation_container.FirstFragment().LocalBorderBoxProperties();
  PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState();

  // Move the point into the source_state transform space, map to dest_state
  // transform space, then move into squashing layer state.
  point.MoveBy(paint_invalidation_container.FirstFragment().PaintOffset());
  point = GeometryMapper::SourceToDestinationProjection(
              source_state.Transform(), dest_state.Transform())
              .MapPoint(point);
  point.MoveBy(-squashing_layer->GetOffsetFromTransformNode());
}

void PaintLayer::MapRectInPaintInvalidationContainerToBacking(
    const LayoutBoxModelObject& paint_invalidation_container,
    LayoutRect& rect) {
  PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer();
  if (!paint_invalidation_layer->GroupedMapping())
    return;

  GraphicsLayer* squashing_layer =
      paint_invalidation_layer->GroupedMapping()->SquashingLayer();

  PropertyTreeState source_state =
      paint_invalidation_container.FirstFragment().LocalBorderBoxProperties();
  PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState();

  // Move the point into the source_state transform space, map to dest_state
  // transform space, then move into squashing layer state.
  rect.MoveBy(paint_invalidation_container.FirstFragment().PaintOffset());
  rect = GeometryMapper::SourceToDestinationProjection(source_state.Transform(),
                                                       dest_state.Transform())
             .MapRect(rect);
  rect.MoveBy(-squashing_layer->GetOffsetFromTransformNode());
}

void PaintLayer::DirtyVisibleContentStatus() {
  MarkAncestorChainForFlagsUpdate();
  // Non-self-painting layers paint into their ancestor layer, and count as part
  // of the "visible contents" of the parent, so we need to dirty it.
  if (!IsSelfPaintingLayer())
    Parent()->DirtyVisibleContentStatus();
}

void PaintLayer::MarkAncestorChainForFlagsUpdate(
    DescendantDependentFlagsUpdateFlag flag) {
#if DCHECK_IS_ON()
  DCHECK(flag == DoesNotNeedDescendantDependentUpdate ||
         !layout_object_.GetDocument()
              .View()
              ->IsUpdatingDescendantDependentFlags());
#endif
  for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
    if (layer->needs_descendant_dependent_flags_update_ &&
        layer->GetLayoutObject().NeedsPaintPropertyUpdate())
      break;
    if (flag == NeedsDescendantDependentUpdate)
      layer->needs_descendant_dependent_flags_update_ = true;
    layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
  }
}

void PaintLayer::UpdateDescendantDependentFlags() {
  if (needs_descendant_dependent_flags_update_) {
    bool old_has_non_isolated_descendant_with_blend_mode =
        has_non_isolated_descendant_with_blend_mode_;
    has_visible_descendant_ = false;
    has_non_isolated_descendant_with_blend_mode_ = false;
    has_descendant_with_clip_path_ = false;
    has_fixed_position_descendant_ = false;
    has_sticky_position_descendant_ = false;
    has_non_contained_absolute_position_descendant_ = false;
    has_self_painting_layer_descendant_ = false;
    is_non_stacked_with_in_flow_stacked_descendant_ = false;

    bool can_contain_abs =
        GetLayoutObject().CanContainAbsolutePositionObjects();

    const ComputedStyle& style = GetLayoutObject().StyleRef();
    bool needs_stacking_node = style.IsStackingContext();
    bool is_stacked = style.IsStacked();

    for (PaintLayer* child = FirstChild(); child;
         child = child->NextSibling()) {
      const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();

      child->UpdateDescendantDependentFlags();

      if (child->has_visible_content_ || child->has_visible_descendant_)
        has_visible_descendant_ = true;

      has_non_isolated_descendant_with_blend_mode_ |=
          (!child->GetLayoutObject().StyleRef().IsStackingContext() &&
           child->HasNonIsolatedDescendantWithBlendMode()) ||
          child->GetLayoutObject().StyleRef().HasBlendMode();

      has_descendant_with_clip_path_ |= child->HasDescendantWithClipPath() ||
                                        child->GetLayoutObject().HasClipPath();

      has_fixed_position_descendant_ |=
          child->HasFixedPositionDescendant() ||
          child_style.GetPosition() == EPosition::kFixed;
      has_sticky_position_descendant_ |=
          child->HasStickyPositionDescendant() ||
          child_style.GetPosition() == EPosition::kSticky;

      if (!can_contain_abs) {
        has_non_contained_absolute_position_descendant_ |=
            (child->HasNonContainedAbsolutePositionDescendant() ||
             child_style.GetPosition() == EPosition::kAbsolute);
      }

      needs_stacking_node = needs_stacking_node || !child_style.IsStacked();

      has_self_painting_layer_descendant_ =
          has_self_painting_layer_descendant_ ||
          child->HasSelfPaintingLayerDescendant() ||
          child->IsSelfPaintingLayer();

      if (!is_stacked) {
        if (child->IsNonStackedWithInFlowStackedDescendant())
          is_non_stacked_with_in_flow_stacked_descendant_ = true;
        else if (child_style.IsStacked() &&
                 !child->GetLayoutObject().IsOutOfFlowPositioned())
          is_non_stacked_with_in_flow_stacked_descendant_ = true;
      }
    }

    UpdateStackingNode(needs_stacking_node);

    if (old_has_non_isolated_descendant_with_blend_mode !=
        static_cast<bool>(has_non_isolated_descendant_with_blend_mode_))
      GetLayoutObject().SetNeedsPaintPropertyUpdate();
    needs_descendant_dependent_flags_update_ = false;

    if (IsSelfPaintingLayer() && needs_visual_overflow_recalc_) {
      LayoutRect old_visual_rect = GetLayoutObject().VisualOverflowRect();
      GetLayoutObject().RecalcVisualOverflow();
      if (old_visual_rect != GetLayoutObject().VisualOverflowRect()) {
        SetNeedsCompositingInputsUpdateInternal();
        MarkAncestorChainForFlagsUpdate(DoesNotNeedDescendantDependentUpdate);
      }
    }
    needs_visual_overflow_recalc_ = false;
  }

  bool previously_has_visible_content = has_visible_content_;
  if (GetLayoutObject().StyleRef().Visibility() == EVisibility::kVisible) {
    has_visible_content_ = true;
  } else {
    // layer may be hidden but still have some visible content, check for this
    has_visible_content_ = false;
    LayoutObject* r = GetLayoutObject().SlowFirstChild();
    while (r) {
      if (r->StyleRef().Visibility() == EVisibility::kVisible &&
          (!r->HasLayer() || !r->EnclosingLayer()->IsSelfPaintingLayer())) {
        has_visible_content_ = true;
        break;
      }
      LayoutObject* layout_object_first_child = r->SlowFirstChild();
      if (layout_object_first_child &&
          (!r->HasLayer() || !r->EnclosingLayer()->IsSelfPaintingLayer())) {
        r = layout_object_first_child;
      } else if (r->NextSibling()) {
        r = r->NextSibling();
      } else {
        do {
          r = r->Parent();
          if (r == &GetLayoutObject())
            r = nullptr;
        } while (r && !r->NextSibling());
        if (r)
          r = r->NextSibling();
      }
    }
  }

  if (HasVisibleContent() != previously_has_visible_content) {
    SetNeedsCompositingInputsUpdateInternal();
    // We need to tell layout_object_ to recheck its rect because we
    // pretend that invisible LayoutObjects have 0x0 rects. Changing
    // visibility therefore changes our rect and we need to visit
    // this LayoutObject during the PrePaintTreeWalk.
    layout_object_.SetShouldCheckForPaintInvalidation();
  }

  Update3DTransformedDescendantStatus();
}

void PaintLayer::Update3DTransformedDescendantStatus() {
  has3d_transformed_descendant_ = false;

  if (!stacking_node_)
    return;

  // Transformed or preserve-3d descendants can only be in the z-order lists,
  // not in the normal flow list, so we only need to check those.
  PaintLayerStackingNodeIterator iterator(
      *stacking_node_.get(), kPositiveZOrderChildren | kNegativeZOrderChildren);
  while (PaintLayer* child_layer = iterator.Next()) {
    bool child_has3d = false;
    // If the child lives in a 3d hierarchy, then the layer at the root of
    // that hierarchy needs the m_has3DTransformedDescendant set.
    if (child_layer->Preserves3D() &&
        (child_layer->Has3DTransform() ||
         child_layer->Has3DTransformedDescendant()))
      child_has3d = true;
    else if (child_layer->Has3DTransform())
      child_has3d = true;

    if (child_has3d) {
      has3d_transformed_descendant_ = true;
      break;
    }
  }
}

void PaintLayer::UpdateLayerPosition() {
  // LayoutBoxes will call UpdateSizeAndScrollingAfterLayout() from
  // LayoutBox::UpdateAfterLayout, but LayoutInlines will still need to update
  // their size.
  if (GetLayoutObject().IsInline() && GetLayoutObject().IsLayoutInline())
    UpdateSizeAndScrollingAfterLayout();
  LayoutPoint local_point;
  if (LayoutBox* box = GetLayoutBox()) {
    local_point.MoveBy(box->PhysicalLocation());
  }

  if (!GetLayoutObject().IsOutOfFlowPositioned() &&
      !GetLayoutObject().IsColumnSpanAll()) {
    // We must adjust our position by walking up the layout tree looking for the
    // nearest enclosing object with a layer.
    LayoutObject* curr = GetLayoutObject().Container();
    while (curr && !curr->HasLayer()) {
      if (curr->IsBox() && !curr->IsTableRow()) {
        // Rows and cells share the same coordinate space (that of the section).
        // Omit them when computing our xpos/ypos.
        local_point.MoveBy(ToLayoutBox(curr)->PhysicalLocation());
      }
      curr = curr->Container();
    }
    if (curr && curr->IsTableRow()) {
      // Put ourselves into the row coordinate space.
      local_point.MoveBy(-ToLayoutBox(curr)->PhysicalLocation());
    }
  }

  if (PaintLayer* containing_layer = ContainingLayer()) {
    if (containing_layer->GetLayoutObject().HasOverflowClip() &&
        !containing_layer->IsRootLayer()) {
      // Subtract our container's scroll offset.
      IntSize offset =
          containing_layer->GetLayoutBox()->ScrolledContentOffset();
      local_point -= offset;
    } else {
      auto& container = containing_layer->GetLayoutObject();
      if (GetLayoutObject().IsOutOfFlowPositioned() &&
          container.IsLayoutInline() &&
          container.CanContainOutOfFlowPositionedElement(
              GetLayoutObject().StyleRef().GetPosition())) {
        // Adjust offset for absolute under in-flow positioned inline.
        LayoutSize offset =
            ToLayoutInline(container).OffsetForInFlowPositionedInline(
                ToLayoutBox(GetLayoutObject()));
        local_point += offset;
      }
    }
  }

  if (GetLayoutObject().IsInFlowPositioned()) {
    LayoutSize new_offset = GetLayoutObject().OffsetForInFlowPosition();
    if (rare_data_ || !new_offset.IsZero())
      EnsureRareData().offset_for_in_flow_position = new_offset;
    local_point.Move(new_offset);
  } else if (rare_data_) {
    rare_data_->offset_for_in_flow_position = LayoutSize();
  }

  location_ = local_point;

#if DCHECK_IS_ON()
  needs_position_update_ = false;
#endif
}

bool PaintLayer::UpdateSize() {
  LayoutSize old_size = size_;
  if (IsRootLayer()) {
    size_ = LayoutSize(GetLayoutObject().GetDocument().View()->Size());
  } else if (GetLayoutObject().IsInline() &&
             GetLayoutObject().IsLayoutInline()) {
    LayoutInline& inline_flow = ToLayoutInline(GetLayoutObject());
    IntRect line_box = EnclosingIntRect(inline_flow.LinesBoundingBox());
    size_ = LayoutSize(line_box.Size());
  } else if (LayoutBox* box = GetLayoutBox()) {
    size_ = box->Size();
  }
  if (old_size != size_)
    SetNeedsCompositingInputsUpdate();

  return old_size != size_;
}

void PaintLayer::UpdateSizeAndScrollingAfterLayout() {
  bool did_resize = UpdateSize();
  if (RequiresScrollableArea()) {
    DCHECK(scrollable_area_);
    scrollable_area_->UpdateAfterLayout();
    if (did_resize)
      scrollable_area_->VisibleSizeChanged();
  }
}

TransformationMatrix PaintLayer::PerspectiveTransform() const {
  if (!GetLayoutObject().HasTransformRelatedProperty())
    return TransformationMatrix();

  const ComputedStyle& style = GetLayoutObject().StyleRef();
  if (!style.HasPerspective())
    return TransformationMatrix();

  TransformationMatrix t;
  t.ApplyPerspective(style.Perspective());
  return t;
}

FloatPoint PaintLayer::PerspectiveOrigin() const {
  if (!GetLayoutObject().HasTransformRelatedProperty())
    return FloatPoint();

  const LayoutRect border_box = ToLayoutBox(GetLayoutObject()).BorderBoxRect();
  const ComputedStyle& style = GetLayoutObject().StyleRef();

  return FloatPointForLengthPoint(style.PerspectiveOrigin(),
                                  FloatSize(border_box.Size()));
}

PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor,
                                        bool* skipped_ancestor) const {
  // If we have specified an ancestor, surely the caller needs to know whether
  // we skipped it.
  DCHECK(!ancestor || skipped_ancestor);
  if (skipped_ancestor)
    *skipped_ancestor = false;

  LayoutObject& layout_object = GetLayoutObject();
  if (layout_object.IsOutOfFlowPositioned()) {
    auto can_contain_this_layer =
        layout_object.IsFixedPositioned()
            ? &LayoutObject::CanContainFixedPositionObjects
            : &LayoutObject::CanContainAbsolutePositionObjects;

    PaintLayer* curr = Parent();
    while (curr && !((&curr->GetLayoutObject())->*can_contain_this_layer)()) {
      if (skipped_ancestor && curr == ancestor)
        *skipped_ancestor = true;
      curr = curr->Parent();
    }
    return curr;
  }

  // If the parent layer is not a block, there might be floating objects
  // between this layer (included) and parent layer which need to escape the
  // inline parent to find the actual containing layer through the containing
  // block chain.
  // Column span need to find the containing layer through its containing block.
  if ((!Parent() || Parent()->GetLayoutObject().IsLayoutBlock()) &&
      !layout_object.IsColumnSpanAll())
    return Parent();

  // This is a universal approach to find containing layer, but is slower than
  // the earlier code.
  base::Optional<LayoutObject::AncestorSkipInfo> skip_info;
  if (skipped_ancestor)
    skip_info.emplace(&ancestor->GetLayoutObject());
  auto* object = &layout_object;
  while (auto* container =
             object->Container(skipped_ancestor ? &*skip_info : nullptr)) {
    if (skipped_ancestor && skip_info->AncestorSkipped())
      *skipped_ancestor = true;
    if (container->HasLayer())
      return ToLayoutBoxModelObject(container)->Layer();
    object = container;
  }
  return nullptr;
}

LayoutPoint PaintLayer::ComputeOffsetFromAncestor(
    const PaintLayer& ancestor_layer) const {
  TransformState transform_state(TransformState::kApplyTransformDirection,
                                 FloatPoint());
  const LayoutBoxModelObject& ancestor_object =
      ancestor_layer.GetLayoutObject();
  GetLayoutObject().MapLocalToAncestor(&ancestor_object, transform_state, 0);
  if (ancestor_object.UsesCompositedScrolling())
    transform_state.Move(ToLayoutBox(ancestor_object).ScrolledContentOffset());
  transform_state.Flatten();
  return LayoutPoint(transform_state.LastPlanarPoint());
}

PaintLayer* PaintLayer::CompositingContainer() const {
  if (IsReplacedNormalFlowStacking())
    return Parent();
  if (!GetLayoutObject().StyleRef().IsStacked())
    return IsSelfPaintingLayer() ? Parent() : ContainingLayer();
  if (PaintLayerStackingNode* ancestor_stacking_node =
          PaintLayerStackingNode::AncestorStackingContextNode(this))
    return ancestor_stacking_node->Layer();
  return nullptr;
}

bool PaintLayer::IsPaintInvalidationContainer() const {
  return GetCompositingState() == kPaintsIntoOwnBacking ||
         GetCompositingState() == kPaintsIntoGroupedBacking;
}

// Note: enclosingCompositingLayer does not include squashed layers. Compositing
// stacking children of squashed layers receive graphics layers that are
// parented to the compositing ancestor of the squashed layer.
PaintLayer* PaintLayer::EnclosingLayerWithCompositedLayerMapping(
    IncludeSelfOrNot include_self) const {
  DCHECK(IsAllowedToQueryCompositingState());

  if ((include_self == kIncludeSelf) &&
      GetCompositingState() != kNotComposited &&
      GetCompositingState() != kPaintsIntoGroupedBacking)
    return const_cast<PaintLayer*>(this);

  for (PaintLayer* curr = CompositingContainer(); curr;
       curr = curr->CompositingContainer()) {
    if (curr->GetCompositingState() != kNotComposited &&
        curr->GetCompositingState() != kPaintsIntoGroupedBacking)
      return curr;
  }

  return nullptr;
}

// Return the enclosingCompositedLayerForPaintInvalidation for the given Layer
// including crossing frame boundaries.
PaintLayer*
PaintLayer::EnclosingLayerForPaintInvalidationCrossingFrameBoundaries() const {
  const PaintLayer* layer = this;
  PaintLayer* composited_layer = nullptr;
  while (!composited_layer) {
    composited_layer = layer->EnclosingLayerForPaintInvalidation();
    if (!composited_layer) {
      CHECK(layer->GetLayoutObject().GetFrame());
      auto* owner = layer->GetLayoutObject().GetFrame()->OwnerLayoutObject();
      if (!owner)
        break;
      layer = owner->EnclosingLayer();
    }
  }
  return composited_layer;
}

PaintLayer* PaintLayer::EnclosingLayerForPaintInvalidation() const {
  DCHECK(IsAllowedToQueryCompositingState());

  if (IsPaintInvalidationContainer())
    return const_cast<PaintLayer*>(this);

  for (PaintLayer* curr = CompositingContainer(); curr;
       curr = curr->CompositingContainer()) {
    if (curr->IsPaintInvalidationContainer())
      return curr;
  }

  return nullptr;
}

void PaintLayer::SetNeedsCompositingInputsUpdate() {
  SetNeedsCompositingInputsUpdateInternal();

  // TODO(chrishtr): These are a bit of a heavy hammer, because not all
  // things which require compositing inputs update require a descendant-
  // dependent flags update. Reduce call sites after CAP launch allows
  /// removal of CompositingInputsUpdater.
  MarkAncestorChainForFlagsUpdate(NeedsDescendantDependentUpdate);
}

void PaintLayer::SetNeedsVisualOverflowRecalc() {
  DCHECK(IsSelfPaintingLayer());
  needs_visual_overflow_recalc_ = true;
  MarkAncestorChainForFlagsUpdate();
}

void PaintLayer::SetNeedsCompositingInputsUpdateInternal() {
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
    return;

  needs_ancestor_dependent_compositing_inputs_update_ = true;

  for (PaintLayer* current = this;
       current && !current->child_needs_compositing_inputs_update_;
       current = current->Parent())
    current->child_needs_compositing_inputs_update_ = true;

  if (Compositor()) {
    Compositor()->SetNeedsCompositingUpdate(
        kCompositingUpdateAfterCompositingInputChange);
  }
}

void PaintLayer::UpdateAncestorDependentCompositingInputs(
    const AncestorDependentCompositingInputs& compositing_inputs) {
  DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
  EnsureAncestorDependentCompositingInputs() = compositing_inputs;
  needs_ancestor_dependent_compositing_inputs_update_ = false;
}

void PaintLayer::ClearChildNeedsCompositingInputsUpdate() {
  DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
  DCHECK(!NeedsCompositingInputsUpdate());
  child_needs_compositing_inputs_update_ = false;
}

bool PaintLayer::HasNonIsolatedDescendantWithBlendMode() const {
  DCHECK(!needs_descendant_dependent_flags_update_);
  if (has_non_isolated_descendant_with_blend_mode_)
    return true;
  if (GetLayoutObject().IsSVGRoot())
    return ToLayoutSVGRoot(GetLayoutObject())
        .HasNonIsolatedBlendingDescendants();
  return false;
}

void PaintLayer::SetCompositingReasons(CompositingReasons reasons,
                                       CompositingReasons mask) {
  CompositingReasons old_reasons =
      rare_data_ ? rare_data_->compositing_reasons : CompositingReason::kNone;
  if ((old_reasons & mask) == (reasons & mask))
    return;
  CompositingReasons new_reasons = (reasons & mask) | (old_reasons & ~mask);
  if (rare_data_ || new_reasons != CompositingReason::kNone)
    EnsureRareData().compositing_reasons = new_reasons;
}

void PaintLayer::SetSquashingDisallowedReasons(
    SquashingDisallowedReasons reasons) {
  SquashingDisallowedReasons old_reasons =
      rare_data_ ? rare_data_->squashing_disallowed_reasons
                 : SquashingDisallowedReason::kNone;
  if (old_reasons == reasons)
    return;
  if (rare_data_ || reasons != SquashingDisallowedReason::kNone)
    EnsureRareData().squashing_disallowed_reasons = reasons;
}

void PaintLayer::SetHasCompositingDescendant(bool has_compositing_descendant) {
  if (has_compositing_descendant_ ==
      static_cast<unsigned>(has_compositing_descendant))
    return;

  has_compositing_descendant_ = has_compositing_descendant;

  if (HasCompositedLayerMapping())
    GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
        kGraphicsLayerUpdateLocal);
}

void PaintLayer::SetShouldIsolateCompositedDescendants(
    bool should_isolate_composited_descendants) {
  if (should_isolate_composited_descendants_ ==
      static_cast<unsigned>(should_isolate_composited_descendants))
    return;

  should_isolate_composited_descendants_ =
      should_isolate_composited_descendants;

  if (HasCompositedLayerMapping())
    GetCompositedLayerMapping()->SetNeedsGraphicsLayerUpdate(
        kGraphicsLayerUpdateLocal);
}

bool PaintLayer::HasAncestorWithFilterThatMovesPixels() const {
  for (const PaintLayer* curr = this; curr; curr = curr->Parent()) {
    if (curr->HasFilterThatMovesPixels())
      return true;
  }
  return false;
}

static void ExpandClipRectForDescendants(
    LayoutRect& clip_rect,
    const PaintLayer* layer,
    const PaintLayer* root_layer,
    PaintLayer::TransparencyClipBoxBehavior transparency_behavior,
    const LayoutSize& sub_pixel_accumulation,
    GlobalPaintFlags global_paint_flags) {
  // If we have a mask, then the clip is limited to the border box area (and
  // there is no need to examine child layers).
  if (!layer->GetLayoutObject().HasMask()) {
    // Note: we don't have to walk z-order lists since transparent elements
    // always establish a stacking container. This means we can just walk the
    // layer tree directly.
    for (PaintLayer* curr = layer->FirstChild(); curr;
         curr = curr->NextSibling())
      clip_rect.Unite(PaintLayer::TransparencyClipBox(
          curr, root_layer, transparency_behavior,
          PaintLayer::kDescendantsOfTransparencyClipBox, sub_pixel_accumulation,
          global_paint_flags));
  }
}

LayoutRect PaintLayer::TransparencyClipBox(
    const PaintLayer* layer,
    const PaintLayer* root_layer,
    TransparencyClipBoxBehavior transparency_behavior,
    TransparencyClipBoxMode transparency_mode,
    const LayoutSize& sub_pixel_accumulation,
    GlobalPaintFlags global_paint_flags) {
  // FIXME: Although this function completely ignores CSS-imposed clipping, we
  // did already intersect with the paintDirtyRect, and that should cut down on
  // the amount we have to paint.  Still it would be better to respect clips.

  if (root_layer != layer &&
      ((transparency_behavior == kPaintingTransparencyClipBox &&
        layer->PaintsWithTransform(global_paint_flags)) ||
       (transparency_behavior == kHitTestingTransparencyClipBox &&
        layer->HasTransformRelatedProperty()))) {
    // The best we can do here is to use enclosed bounding boxes to establish a
    // "fuzzy" enough clip to encompass the transformed layer and all of its
    // children.
    const PaintLayer* pagination_layer =
        transparency_mode == kDescendantsOfTransparencyClipBox
            ? layer->EnclosingPaginationLayer()
            : nullptr;
    const PaintLayer* root_layer_for_transform =
        pagination_layer ? pagination_layer : root_layer;
    LayoutPoint delta;
    layer->ConvertToLayerCoords(root_layer_for_transform, delta);

    delta.Move(sub_pixel_accumulation);
    IntPoint pixel_snapped_delta = RoundedIntPoint(delta);
    TransformationMatrix transform;
    transform.Translate(pixel_snapped_delta.X(), pixel_snapped_delta.Y());
    if (layer->Transform())
      transform = transform * *layer->Transform();

    // We don't use fragment boxes when collecting a transformed layer's
    // bounding box, since it always paints unfragmented.
    LayoutRect clip_rect = layer->PhysicalBoundingBox(LayoutPoint());
    ExpandClipRectForDescendants(clip_rect, layer, layer, transparency_behavior,
                                 sub_pixel_accumulation, global_paint_flags);
    LayoutRect result = EnclosingLayoutRect(
        transform.MapRect(layer->MapRectForFilter(FloatRect(clip_rect))));
    if (!pagination_layer)
      return result;

    // We have to break up the transformed extent across our columns.
    // Split our box up into the actual fragment boxes that layout in the
    // columns/pages and unite those together to get our true bounding box.
    LayoutFlowThread& enclosing_flow_thread =
        ToLayoutFlowThread(pagination_layer->GetLayoutObject());
    result = enclosing_flow_thread.FragmentsBoundingBox(result);

    LayoutPoint root_layer_delta;
    pagination_layer->ConvertToLayerCoords(root_layer, root_layer_delta);
    result.MoveBy(root_layer_delta);
    return result;
  }

  LayoutRect clip_rect = layer->ShouldFragmentCompositedBounds(root_layer)
                             ? layer->FragmentsBoundingBox(root_layer)
                             : layer->PhysicalBoundingBox(root_layer);
  ExpandClipRectForDescendants(clip_rect, layer, root_layer,
                               transparency_behavior, sub_pixel_accumulation,
                               global_paint_flags);

  // Convert clipRect into local coordinates for mapLayerRectForFilter(), and
  // convert back after.
  LayoutPoint delta;
  layer->ConvertToLayerCoords(root_layer, delta);
  clip_rect.MoveBy(-delta);
  clip_rect = layer->MapLayoutRectForFilter(clip_rect);
  clip_rect.MoveBy(delta);

  clip_rect.Move(sub_pixel_accumulation);
  return clip_rect;
}

LayoutRect PaintLayer::PaintingExtent(const PaintLayer* root_layer,
                                      const LayoutSize& sub_pixel_accumulation,
                                      GlobalPaintFlags global_paint_flags) {
  return TransparencyClipBox(this, root_layer, kPaintingTransparencyClipBox,
                             kRootOfTransparencyClipBox, sub_pixel_accumulation,
                             global_paint_flags);
}

void* PaintLayer::operator new(size_t sz) {
  return WTF::Partitions::LayoutPartition()->Alloc(
      sz, WTF_HEAP_PROFILER_TYPE_NAME(PaintLayer));
}

void PaintLayer::operator delete(void* ptr) {
  base::PartitionFree(ptr);
}

void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
  PaintLayer* prev_sibling =
      before_child ? before_child->PreviousSibling() : LastChild();
  if (prev_sibling) {
    child->SetPreviousSibling(prev_sibling);
    prev_sibling->SetNextSibling(child);
    DCHECK(prev_sibling != child);
  } else {
    SetFirstChild(child);
  }

  if (before_child) {
    before_child->SetPreviousSibling(child);
    child->SetNextSibling(before_child);
    DCHECK(before_child != child);
  } else {
    SetLastChild(child);
  }

  child->parent_ = this;

  // The ancestor overflow layer is calculated during compositing inputs update
  // and should not be set yet.
  CHECK(!child->AncestorOverflowLayer());

  SetNeedsCompositingInputsUpdate();

  const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();

  if (Compositor()) {
    if (!child_style.IsStacked() && !GetLayoutObject().DocumentBeingDestroyed())
      Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
  }

  if (child_style.IsStacked() || child->FirstChild()) {
    // Dirty the z-order list in which we are contained. The
    // ancestorStackingContextNode() can be null in the case where we're
    // building up generated content layers. This is ok, since the lists will
    // start off dirty in that case anyway.
    PaintLayerStackingNode::DirtyStackingContextZOrderLists(child);
    MarkAncestorChainForFlagsUpdate();
  }

  // Non-self-painting children paint into this layer, so the visible contents
  // status of this layer is affected.
  if (!child->IsSelfPaintingLayer())
    DirtyVisibleContentStatus();

  MarkAncestorChainForFlagsUpdate();

  // Need to force requirements update, due to change of stacking order.
  SetNeedsCompositingRequirementsUpdate();

  child->SetNeedsRepaint();
}

PaintLayer* PaintLayer::RemoveChild(PaintLayer* old_child) {
  old_child->MarkCompositingContainerChainForNeedsRepaint();

  if (old_child->PreviousSibling())
    old_child->PreviousSibling()->SetNextSibling(old_child->NextSibling());
  if (old_child->NextSibling())
    old_child->NextSibling()->SetPreviousSibling(old_child->PreviousSibling());

  if (first_ == old_child)
    first_ = old_child->NextSibling();
  if (last_ == old_child)
    last_ = old_child->PreviousSibling();

  const ComputedStyle& old_child_style =
      old_child->GetLayoutObject().StyleRef();

  if (!GetLayoutObject().DocumentBeingDestroyed()) {
    if (Compositor()) {
      if (!old_child_style.IsStacked())
        Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
    }
    // Dirty the z-order list in which we are contained.
    PaintLayerStackingNode::DirtyStackingContextZOrderLists(old_child);
    SetNeedsCompositingInputsUpdate();
  }

  if (GetLayoutObject().StyleRef().Visibility() != EVisibility::kVisible)
    DirtyVisibleContentStatus();

  old_child->SetPreviousSibling(nullptr);
  old_child->SetNextSibling(nullptr);
  old_child->parent_ = nullptr;

  // Remove any ancestor overflow layers which descended into the removed child.
  if (old_child->AncestorOverflowLayer())
    old_child->RemoveAncestorOverflowLayer(old_child->AncestorOverflowLayer());

  if (old_child->has_visible_content_ || old_child->has_visible_descendant_)
    MarkAncestorChainForFlagsUpdate();

  if (old_child->EnclosingPaginationLayer())
    old_child->ClearPaginationRecursive();

  return old_child;
}

void PaintLayer::ClearClipRects(ClipRectsCacheSlot cache_slot) {
  Clipper(GeometryMapperOption::kDoNotUseGeometryMapper)
      .ClearClipRectsIncludingDescendants(cache_slot);
}

void PaintLayer::RemoveOnlyThisLayerAfterStyleChange(
    const ComputedStyle* old_style) {
  if (!parent_)
    return;

  if (old_style && old_style->IsStacked()) {
    PaintLayerStackingNode::DirtyStackingContextZOrderLists(this);
    MarkAncestorChainForFlagsUpdate();
  }

  bool did_set_paint_invalidation = false;
  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
    // Destructing PaintLayer would cause CompositedLayerMapping and composited
    // layers to be destructed and detach from layer tree immediately. Layers
    // could have dangling scroll/clip parent if compositing update were
    // omitted.
    if (LocalFrameView* frame_view = layout_object_.GetDocument().View())
      frame_view->SetNeedsForcedCompositingUpdate();

    // We need the current compositing status.
    DisableCompositingQueryAsserts disabler;
    if (IsPaintInvalidationContainer()) {
      // Our children will be reparented and contained by a new paint
      // invalidation container, so need paint invalidation. CompositingUpdate
      // can't see this layer (which has been removed) so won't do this for us.
      ObjectPaintInvalidator(GetLayoutObject())
          .InvalidatePaintIncludingNonCompositingDescendants();
      GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation();
      did_set_paint_invalidation = true;
    }
  }

  if (!did_set_paint_invalidation && IsSelfPaintingLayer()) {
    if (PaintLayer* enclosing_self_painting_layer =
            parent_->EnclosingSelfPaintingLayer())
      enclosing_self_painting_layer->MergeNeedsPaintPhaseFlagsFrom(*this);
  }

  ClearClipRects();

  PaintLayer* next_sib = NextSibling();

  // Now walk our kids and reattach them to our parent.
  PaintLayer* current = first_;
  while (current) {
    PaintLayer* next = current->NextSibling();
    RemoveChild(current);
    parent_->AddChild(current, next_sib);

    // FIXME: We should call a specialized version of this function.
    current->UpdateLayerPositionsAfterLayout();
    current = next;
  }

  // Remove us from the parent.
  parent_->RemoveChild(this);
  layout_object_.DestroyLayer();
}

void PaintLayer::InsertOnlyThisLayerAfterStyleChange() {
  if (!parent_ && GetLayoutObject().Parent()) {
    // We need to connect ourselves when our layoutObject() has a parent.
    // Find our enclosingLayer and add ourselves.
    PaintLayer* parent_layer = GetLayoutObject().Parent()->EnclosingLayer();
    DCHECK(parent_layer);
    PaintLayer* before_child = GetLayoutObject().Parent()->FindNextLayer(
        parent_layer, &GetLayoutObject());
    parent_layer->AddChild(this, before_child);
  }

  // Remove all descendant layers from the hierarchy and add them to the new
  // position.
  for (LayoutObject* curr = GetLayoutObject().SlowFirstChild(); curr;
       curr = curr->NextSibling())
    curr->MoveLayers(parent_, this);

  // If the previous paint invalidation container is not a stacking context and
  // this object is stacked content, creating this layer may cause this object
  // and its descendants to change paint invalidation container.
  bool did_set_paint_invalidation = false;
  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
      !GetLayoutObject().IsLayoutView() && GetLayoutObject().IsRooted() &&
      GetLayoutObject().StyleRef().IsStacked()) {
    const LayoutBoxModelObject& previous_paint_invalidation_container =
        GetLayoutObject().Parent()->ContainerForPaintInvalidation();
    if (!previous_paint_invalidation_container.StyleRef().IsStackingContext()) {
      ObjectPaintInvalidator(GetLayoutObject())
          .InvalidatePaintIncludingNonSelfPaintingLayerDescendants();
      // Set needsRepaint along the original compositingContainer chain.
      GetLayoutObject().Parent()->EnclosingLayer()->SetNeedsRepaint();
      did_set_paint_invalidation = true;
    }
  }

  if (!did_set_paint_invalidation && IsSelfPaintingLayer() && parent_) {
    if (PaintLayer* enclosing_self_painting_layer =
            parent_->EnclosingSelfPaintingLayer())
      MergeNeedsPaintPhaseFlagsFrom(*enclosing_self_painting_layer);
  }

  // Clear out all the clip rects.
  ClearClipRects();
}

// Returns the layer reached on the walk up towards the ancestor.
static inline const PaintLayer* AccumulateOffsetTowardsAncestor(
    const PaintLayer* layer,
    const PaintLayer* ancestor_layer,
    LayoutPoint& location) {
  DCHECK(ancestor_layer != layer);

  const LayoutBoxModelObject& layout_object = layer->GetLayoutObject();

  if (layout_object.IsFixedPositioned() &&
      (!ancestor_layer || ancestor_layer == layout_object.View()->Layer())) {
    // If the fixed layer's container is the root, just add in the offset of the
    // view. We can obtain this by calling localToAbsolute() on the LayoutView.
    FloatPoint abs_pos = layout_object.LocalToAbsolute();
    location += LayoutSize(abs_pos.X(), abs_pos.Y());
    return ancestor_layer;
  }

  bool found_ancestor_first;
  PaintLayer* containing_layer =
      layer->ContainingLayer(ancestor_layer, &found_ancestor_first);

  if (found_ancestor_first) {
    // Found ancestorLayer before the containing layer, so compute offset of
    // both relative to the container and subtract.
    LayoutPoint this_coords;
    layer->ConvertToLayerCoords(containing_layer, this_coords);

    LayoutPoint ancestor_coords;
    ancestor_layer->ConvertToLayerCoords(containing_layer, ancestor_coords);

    location += (this_coords - ancestor_coords);
    return ancestor_layer;
  }

  if (!containing_layer)
    return nullptr;

  location += layer->Location();
  return containing_layer;
}

void PaintLayer::ConvertToLayerCoords(const PaintLayer* ancestor_layer,
                                      LayoutPoint& location) const {
  if (ancestor_layer == this)
    return;

  const PaintLayer* curr_layer = this;
  while (curr_layer && curr_layer != ancestor_layer)
    curr_layer =
        AccumulateOffsetTowardsAncestor(curr_layer, ancestor_layer, location);
}

void PaintLayer::ConvertToLayerCoords(const PaintLayer* ancestor_layer,
                                      LayoutRect& rect) const {
  LayoutPoint delta;
  ConvertToLayerCoords(ancestor_layer, delta);
  rect.MoveBy(delta);
}

LayoutPoint PaintLayer::VisualOffsetFromAncestor(
    const PaintLayer* ancestor_layer,
    LayoutPoint offset) const {
  if (ancestor_layer == this)
    return offset;
  PaintLayer* pagination_layer = EnclosingPaginationLayer();
  if (pagination_layer == this)
    pagination_layer = Parent()->EnclosingPaginationLayer();
  if (!pagination_layer) {
    ConvertToLayerCoords(ancestor_layer, offset);
    return offset;
  }

  LayoutFlowThread& flow_thread =
      ToLayoutFlowThread(pagination_layer->GetLayoutObject());
  ConvertToLayerCoords(pagination_layer, offset);
  offset = flow_thread.FlowThreadPointToVisualPoint(offset);
  if (ancestor_layer == pagination_layer)
    return offset;

  if (ancestor_layer->EnclosingPaginationLayer() != pagination_layer) {
    offset.MoveBy(pagination_layer->VisualOffsetFromAncestor(ancestor_layer));
  } else {
    // The ancestor layer is also inside the pagination layer, so we need to
    // subtract the visual distance from the ancestor layer to the pagination
    // layer.
    offset.MoveBy(-ancestor_layer->VisualOffsetFromAncestor(pagination_layer));
  }
  return offset;
}

void PaintLayer::DidUpdateScrollsOverflow() {
  UpdateSelfPaintingLayer();
}

void PaintLayer::UpdateStackingNode(bool needs_stacking_node) {
  if (needs_stacking_node != !!stacking_node_) {
    if (needs_stacking_node)
      stacking_node_ = std::make_unique<PaintLayerStackingNode>(this);
    else
      stacking_node_ = nullptr;
  }

  if (stacking_node_)
    stacking_node_->UpdateZOrderLists();
}

bool PaintLayer::RequiresScrollableArea() const {
  if (!GetLayoutBox())
    return false;
  if (GetLayoutObject().HasOverflowClip())
    return true;
  // Iframes with the resize property can be resized. This requires
  // scroll corner painting, which is implemented, in part, by
  // PaintLayerScrollableArea.
  if (GetLayoutBox()->CanResize())
    return true;
  return false;
}

void PaintLayer::UpdateScrollableArea() {
  if (RequiresScrollableArea() && !scrollable_area_) {
    scrollable_area_ = PaintLayerScrollableArea::Create(*this);
    Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
  } else if (!RequiresScrollableArea() && scrollable_area_) {
    scrollable_area_->Dispose();
    scrollable_area_.Clear();
    Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
  }
}

bool PaintLayer::HasOverflowControls() const {
  return scrollable_area_ &&
         (scrollable_area_->HasScrollbar() ||
          scrollable_area_->ScrollCorner() ||
          GetLayoutObject().StyleRef().Resize() != EResize::kNone);
}

void PaintLayer::AppendSingleFragmentIgnoringPagination(
    PaintLayerFragments& fragments,
    const PaintLayer* root_layer,
    const CullRect* cull_rect,
    OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
    ShouldRespectOverflowClipType respect_overflow_clip,
    const LayoutPoint* offset_from_root,
    const LayoutSize& sub_pixel_accumulation) const {
  PaintLayerFragment fragment;
  ClipRectsContext clip_rects_context(
      root_layer, &root_layer->GetLayoutObject().FirstFragment(),
      kUncachedClipRects, overlay_scrollbar_clip_behavior,
      respect_overflow_clip, sub_pixel_accumulation);
  Clipper(GeometryMapperOption::kUseGeometryMapper)
      .CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(),
                      cull_rect, fragment.layer_bounds,
                      fragment.background_rect, fragment.foreground_rect,
                      offset_from_root);
  fragment.root_fragment_data = &root_layer->GetLayoutObject().FirstFragment();
  fragment.fragment_data = &GetLayoutObject().FirstFragment();
  fragments.push_back(fragment);
}

bool PaintLayer::ShouldFragmentCompositedBounds(
    const PaintLayer* compositing_layer) const {
  if (!EnclosingPaginationLayer())
    return false;
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
    return true;
  if (PaintsWithTransform(kGlobalPaintNormalPhase))
    return true;
  if (!compositing_layer) {
    compositing_layer =
        EnclosingLayerForPaintInvalidationCrossingFrameBoundaries();
  }
  if (!compositing_layer)
    return true;
  // Composited layers may not be fragmented.
  return !compositing_layer->EnclosingPaginationLayer();
}

void PaintLayer::CollectFragments(
    PaintLayerFragments& fragments,
    const PaintLayer* root_layer,
    const CullRect* cull_rect,
    OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
    ShouldRespectOverflowClipType respect_overflow_clip,
    const LayoutPoint* offset_from_root,
    const LayoutSize& sub_pixel_accumulation) const {
  PaintLayerFragment fragment;
  const auto& first_fragment_data = GetLayoutObject().FirstFragment();
  const auto& first_root_fragment_data =
      root_layer->GetLayoutObject().FirstFragment();

  // If both |this| and |root_layer| are fragmented and are inside the same
  // pagination container, then try to match fragments from |root_layer| to
  // |this|, so that any fragment clip for |root_layer|'s fragment matches
  // |this|'s. Note we check both ShouldFragmentCompositedBounds() and next
  // fragment here because the former may return false even if |this| is
  // fragmented, e.g. for fixed-position objects in paged media, and the next
  // fragment can be null even if the first fragment is actually in a fragmented
  // context when the current layer appears in only one of the multiple
  // fragments of the pagination container.
  bool is_fragmented =
      ShouldFragmentCompositedBounds() || first_fragment_data.NextFragment();
  bool should_match_fragments =
      is_fragmented &&
      root_layer->EnclosingPaginationLayer() == EnclosingPaginationLayer();

  // The inherited offset_from_root does not include any pagination offsets.
  // In the presence of fragmentation, we cannot use it.
  bool offset_from_root_can_be_used = offset_from_root && !is_fragmented;
  for (auto* fragment_data = &first_fragment_data; fragment_data;
       fragment_data = fragment_data->NextFragment()) {
    const FragmentData* root_fragment_data;
    if (root_layer == this) {
      root_fragment_data = fragment_data;
    } else if (should_match_fragments) {
      for (root_fragment_data = &first_root_fragment_data; root_fragment_data;
           root_fragment_data = root_fragment_data->NextFragment()) {
        if (root_fragment_data->LogicalTopInFlowThread() ==
            fragment_data->LogicalTopInFlowThread())
          break;
      }
    } else {
      root_fragment_data = &first_root_fragment_data;
    }

    bool cant_find_fragment = !root_fragment_data;
    if (cant_find_fragment) {
      DCHECK(should_match_fragments);
      // Fall back to the first fragment, in order to have
      // PaintLayerClipper at least compute |fragment.layer_bounds|.
      root_fragment_data = &first_root_fragment_data;
    }

    ClipRectsContext clip_rects_context(
        root_layer, root_fragment_data, kUncachedClipRects,
        overlay_scrollbar_clip_behavior, respect_overflow_clip,
        sub_pixel_accumulation);

    base::Optional<CullRect> fragment_cull_rect;
    if (cull_rect) {
      // |cull_rect| is in the coordinate space of |root_layer| (i.e. the
      // space of |root_layer|'s first fragment). Map the rect to the space of
      // the current root fragment.
      auto rect = cull_rect->Rect();
      first_root_fragment_data.MapRectToFragment(*root_fragment_data, rect);
      fragment_cull_rect.emplace(rect);
    }

    Clipper(GeometryMapperOption::kUseGeometryMapper)
        .CalculateRects(
            clip_rects_context, fragment_data,
            fragment_cull_rect ? &*fragment_cull_rect : nullptr,
            fragment.layer_bounds, fragment.background_rect,
            fragment.foreground_rect,
            offset_from_root_can_be_used ? offset_from_root : nullptr);

    if (cant_find_fragment) {
      // If we couldn't find a matching fragment when |should_match_fragments|
      // was true, then fall back to no clip.
      fragment.background_rect.Reset();
      fragment.foreground_rect.Reset();
    }

    fragment.root_fragment_data = root_fragment_data;
    fragment.fragment_data = fragment_data;

    fragments.push_back(fragment);
  }
}

PaintLayer::HitTestRecursionData::HitTestRecursionData(
    const LayoutRect& rect_arg,
    const HitTestLocation& location_arg,
    const HitTestLocation& original_location_arg)
    : rect(rect_arg),
      location(location_arg),
      original_location(original_location_arg),
      intersects_location(location_arg.Intersects(rect_arg)) {}

bool PaintLayer::HitTest(const HitTestLocation& hit_test_location,
                         HitTestResult& result,
                         const LayoutRect& hit_test_area) {
  DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant());

  // LayoutView should make sure to update layout before entering hit testing
  DCHECK(!GetLayoutObject().GetFrame()->View()->LayoutPending());
  DCHECK(!GetLayoutObject().GetDocument().GetLayoutView()->NeedsLayout());

  const HitTestRequest& request = result.GetHitTestRequest();

  HitTestRecursionData recursion_data(hit_test_area, hit_test_location,
                                      hit_test_location);
  PaintLayer* inside_layer =
      HitTestLayer(this, nullptr, result, recursion_data, false);
  if (!inside_layer && IsRootLayer()) {
    bool fallback = false;
    // If we didn't hit any layers but are still inside the document
    // bounds, then we should fallback to hitting the document.
    // For rect-based hit test, we do the fallback only when the hit-rect
    // is totally within the document bounds.
    if (hit_test_area.Contains(hit_test_location.BoundingBox())) {
      fallback = true;

      // Mouse dragging outside the main document should also be
      // delivered to the document.
      // TODO(miletus): Capture behavior inconsistent with iframes
      // crbug.com/522109.
      // TODO(majidvp): This should apply more consistently across different
      // event types and we should not use RequestType for it. Perhaps best for
      // it to be done at a higher level. See http://crbug.com/505825
    } else if ((request.Active() || request.Release()) &&
               !request.IsChildFrameHitTest()) {
      fallback = true;
    }
    if (fallback) {
      GetLayoutObject().UpdateHitTestResult(
          result, ToLayoutView(GetLayoutObject())
                      .FlipForWritingMode(hit_test_location.Point()));
      inside_layer = this;

      // Don't cache this result since it really wasn't a true hit.
      result.SetCacheable(false);
    }
  }

  // Now determine if the result is inside an anchor - if the urlElement isn't
  // already set.
  Node* node = result.InnerNode();
  if (node && !result.URLElement())
    result.SetURLElement(node->EnclosingLinkEventParentOrSelf());

  // Now return whether we were inside this layer (this will always be true for
  // the root layer).
  return inside_layer;
}

Node* PaintLayer::EnclosingNode() const {
  for (LayoutObject* r = &GetLayoutObject(); r; r = r->Parent()) {
    if (Node* e = r->GetNode())
      return e;
  }
  NOTREACHED();
  return nullptr;
}

bool PaintLayer::IsInTopLayer() const {
  Node* node = GetLayoutObject().GetNode();
  return node && node->IsElementNode() && ToElement(node)->IsInTopLayer();
}

// Compute the z-offset of the point in the transformState.
// This is effectively projecting a ray normal to the plane of ancestor, finding
// where that ray intersects target, and computing the z delta between those two
// points.
static double ComputeZOffset(const HitTestingTransformState& transform_state) {
  // We got an affine transform, so no z-offset
  if (transform_state.accumulated_transform_.IsAffine())
    return 0;

  // Flatten the point into the target plane
  FloatPoint target_point = transform_state.MappedPoint();

  // Now map the point back through the transform, which computes Z.
  FloatPoint3D backmapped_point =
      transform_state.accumulated_transform_.MapPoint(
          FloatPoint3D(target_point));
  return backmapped_point.Z();
}

HitTestingTransformState PaintLayer::CreateLocalTransformState(
    PaintLayer* root_layer,
    PaintLayer* container_layer,
    const HitTestRecursionData& recursion_data,
    const HitTestingTransformState* container_transform_state,
    const LayoutPoint& translation_offset) const {
  // If we're already computing transform state, then it's relative to the
  // container (which we know is non-null).
  // If this is the first time we need to make transform state, then base it
  // off of hitTestLocation, which is relative to rootLayer.
  HitTestingTransformState transform_state =
      container_transform_state
          ? *container_transform_state
          : HitTestingTransformState(recursion_data.location.TransformedPoint(),
                                     recursion_data.location.TransformedRect(),
                                     FloatQuad(FloatRect(recursion_data.rect)));

  LayoutPoint offset;
  if (container_transform_state)
    ConvertToLayerCoords(container_layer, offset);
  else
    ConvertToLayerCoords(root_layer, offset);

  offset.MoveBy(translation_offset);

  LayoutObject* container_layout_object =
      container_layer ? &container_layer->GetLayoutObject() : nullptr;
  if (GetLayoutObject().ShouldUseTransformFromContainer(
          container_layout_object)) {
    TransformationMatrix container_transform;
    GetLayoutObject().GetTransformFromContainer(
        container_layout_object, ToLayoutSize(offset), container_transform);
    transform_state.ApplyTransform(
        container_transform, HitTestingTransformState::kAccumulateTransform);
  } else {
    transform_state.Translate(offset.X().ToInt(), offset.Y().ToInt(),
                              HitTestingTransformState::kAccumulateTransform);
  }

  return transform_state;
}

static bool IsHitCandidate(const PaintLayer* hit_layer,
                           bool can_depth_sort,
                           double* z_offset,
                           const HitTestingTransformState* transform_state) {
  if (!hit_layer)
    return false;

  // The hit layer is depth-sorting with other layers, so just say that it was
  // hit.
  if (can_depth_sort)
    return true;

  // We need to look at z-depth to decide if this layer was hit.
  if (z_offset) {
    DCHECK(transform_state);
    // This is actually computing our z, but that's OK because the hitLayer is
    // coplanar with us.
    double child_z_offset = ComputeZOffset(*transform_state);
    if (child_z_offset > *z_offset) {
      *z_offset = child_z_offset;
      return true;
    }
    return false;
  }

  return true;
}

// hitTestLocation and hitTestRect are relative to rootLayer.
// A 'flattening' layer is one preserves3D() == false.
// transformState.m_accumulatedTransform holds the transform from the containing
// flattening layer.
// transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the
// containing flattening layer.
// transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of
// the containing flattening layer.
//
// If zOffset is non-null (which indicates that the caller wants z offset
// information), *zOffset on return is the z offset of the hit point relative to
// the containing flattening layer.
PaintLayer* PaintLayer::HitTestLayer(PaintLayer* root_layer,
                                     PaintLayer* container_layer,
                                     HitTestResult& result,
                                     const HitTestRecursionData& recursion_data,
                                     bool applied_transform,
                                     HitTestingTransformState* transform_state,
                                     double* z_offset) {
  const LayoutObject& layout_object = GetLayoutObject();
  if (layout_object.PaintBlockedByDisplayLock())
    return nullptr;

  DCHECK_GE(layout_object.GetDocument().Lifecycle().GetState(),
            DocumentLifecycle::kCompositingClean);

  if (!IsSelfPaintingLayer() && !HasSelfPaintingLayerDescendant())
    return nullptr;

  if ((result.GetHitTestRequest().GetType() &
       HitTestRequest::kIgnoreZeroOpacityObjects) &&
      !layout_object.HasNonZeroEffectiveOpacity()) {
    return nullptr;
  }

  ShouldRespectOverflowClipType clip_behavior = kRespectOverflowClip;
  if (result.GetHitTestRequest().IgnoreClipping())
    clip_behavior = kIgnoreOverflowClip;

  // We can only reach an SVG foreign object's PaintLayer from
  // LayoutSVGForeignObject::NodeAtFloatPoint (because
  // IsReplacedNormalFlowStacking() true for LayoutSVGForeignObject),
  // where the hit_test_rect has already been transformed to local coordinates.
  bool use_transform = Transform() && !layout_object.IsSVGForeignObject();

  // Apply a transform if we have one.
  if (use_transform && !applied_transform) {
    if (EnclosingPaginationLayer()) {
      return HitTestTransformedLayerInFragments(
          root_layer, container_layer, result, recursion_data, transform_state,
          z_offset, clip_behavior);
    }

    // Make sure the parent's clip rects have been calculated.
    if (Parent()) {
      ClipRect clip_rect;
      Clipper(GeometryMapperOption::kUseGeometryMapper)
          .CalculateBackgroundClipRect(
              ClipRectsContext(
                  root_layer, &root_layer->GetLayoutObject().FirstFragment(),
                  kUncachedClipRects, kExcludeOverlayScrollbarSizeForHitTesting,
                  clip_behavior),
              clip_rect);
      // Go ahead and test the enclosing clip now.
      if (!clip_rect.Intersects(recursion_data.location))
        return nullptr;
    }

    return HitTestLayerByApplyingTransform(root_layer, container_layer, result,
                                           recursion_data, transform_state,
                                           z_offset);
  }

  if (layout_object.HasClipPath() &&
      HitTestClippedOutByClipPath(root_layer, recursion_data.location))
    return nullptr;

  // The natural thing would be to keep HitTestingTransformState on the stack,
  // but it's big, so we heap-allocate.
  HitTestingTransformState* local_transform_state = nullptr;
  base::Optional<HitTestingTransformState> storage;

  if (applied_transform) {
    // We computed the correct state in the caller (above code), so just
    // reference it.
    DCHECK(transform_state);
    local_transform_state = transform_state;
  } else if (transform_state || has3d_transformed_descendant_ ||
             Preserves3D()) {
    // We need transform state for the first time, or to offset the container
    // state, so create it here.
    storage = CreateLocalTransformState(root_layer, container_layer,
                                        recursion_data, transform_state);
    local_transform_state = &*storage;
  }

  // Check for hit test on backface if backface-visibility is 'hidden'
  if (local_transform_state && layout_object.StyleRef().BackfaceVisibility() ==
                                   EBackfaceVisibility::kHidden) {
    TransformationMatrix inverted_matrix =
        local_transform_state->accumulated_transform_.Inverse();
    // If the z-vector of the matrix is negative, the back is facing towards the
    // viewer.
    if (inverted_matrix.M33() < 0)
      return nullptr;
  }

  HitTestingTransformState* unflattened_transform_state = local_transform_state;
  base::Optional<HitTestingTransformState> unflattened_storage;
  if (local_transform_state && !Preserves3D()) {
    // Keep a copy of the pre-flattening state, for computing z-offsets for the
    // container
    unflattened_storage.emplace(*local_transform_state);
    unflattened_transform_state = &*unflattened_storage;
    // This layer is flattening, so flatten the state passed to descendants.
    local_transform_state->Flatten();
  }

  // The following are used for keeping track of the z-depth of the hit point of
  // 3d-transformed descendants.
  double local_z_offset = -std::numeric_limits<double>::infinity();
  double* z_offset_for_descendants_ptr = nullptr;
  double* z_offset_for_contents_ptr = nullptr;

  bool depth_sort_descendants = false;
  if (Preserves3D()) {
    depth_sort_descendants = true;
    // Our layers can depth-test with our container, so share the z depth
    // pointer with the container, if it passed one down.
    z_offset_for_descendants_ptr = z_offset ? z_offset : &local_z_offset;
    z_offset_for_contents_ptr = z_offset ? z_offset : &local_z_offset;
  } else if (z_offset) {
    z_offset_for_descendants_ptr = nullptr;
    // Container needs us to give back a z offset for the hit layer.
    z_offset_for_contents_ptr = z_offset;
  }

  // This variable tracks which layer the mouse ends up being inside.
  PaintLayer* candidate_layer = nullptr;

  // Begin by walking our list of positive layers from highest z-index down to
  // the lowest z-index.
  PaintLayer* hit_layer = HitTestChildren(
      kPositiveZOrderChildren, root_layer, result, recursion_data,
      local_transform_state, z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state, depth_sort_descendants);
  if (hit_layer) {
    if (!depth_sort_descendants)
      return hit_layer;
    candidate_layer = hit_layer;
  }

  // Now check our overflow objects.
  hit_layer = HitTestChildren(
      kNormalFlowChildren, root_layer, result, recursion_data,
      local_transform_state, z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state, depth_sort_descendants);
  if (hit_layer) {
    if (!depth_sort_descendants)
      return hit_layer;
    candidate_layer = hit_layer;
  }

  // Collect the fragments. This will compute the clip rectangles for each
  // layer fragment.
  base::Optional<PaintLayerFragments> layer_fragments;
  LayoutPoint offset;
  if (recursion_data.intersects_location) {
    layer_fragments.emplace();
    if (applied_transform) {
      DCHECK(root_layer == this);
      LayoutPoint ignored;
      AppendSingleFragmentIgnoringPagination(
          *layer_fragments, root_layer, nullptr,
          kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &ignored);
    } else {
      CollectFragments(*layer_fragments, root_layer, nullptr,
                       kExcludeOverlayScrollbarSizeForHitTesting,
                       clip_behavior);
    }

    if (scrollable_area_ && scrollable_area_->HitTestResizerInFragments(
                                *layer_fragments, recursion_data.location)) {
      layout_object.UpdateHitTestResult(result,
                                        recursion_data.location.Point());
      return this;
    }

    // Next we want to see if the mouse pos is inside the child LayoutObjects of
    // the layer. Check every fragment in reverse order.
    if (IsSelfPaintingLayer()) {
      offset = -LayoutBoxLocation();
      // Hit test with a temporary HitTestResult, because we only want to commit
      // to 'result' if we know we're frontmost.
      HitTestResult temp_result(result.GetHitTestRequest(),
                                recursion_data.original_location);
      bool inside_fragment_foreground_rect = false;

      if (HitTestContentsForFragments(
              *layer_fragments, offset, temp_result, recursion_data.location,
              kHitTestDescendants, inside_fragment_foreground_rect) &&
          IsHitCandidate(this, false, z_offset_for_contents_ptr,
                         unflattened_transform_state)) {
        if (result.GetHitTestRequest().ListBased())
          result.Append(temp_result);
        else
          result = temp_result;
        if (!depth_sort_descendants)
          return this;
        // Foreground can depth-sort with descendant layers, so keep this as a
        // candidate.
        candidate_layer = this;
      } else if (inside_fragment_foreground_rect &&
                 result.GetHitTestRequest().ListBased()) {
        result.Append(temp_result);
      }
    }
  }

  // Now check our negative z-index children.
  hit_layer = HitTestChildren(
      kNegativeZOrderChildren, root_layer, result, recursion_data,
      local_transform_state, z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state, depth_sort_descendants);
  if (hit_layer) {
    if (!depth_sort_descendants)
      return hit_layer;
    candidate_layer = hit_layer;
  }

  // If we found a layer, return. Child layers, and foreground always render
  // in front of background.
  if (candidate_layer)
    return candidate_layer;

  if (recursion_data.intersects_location && IsSelfPaintingLayer()) {
    HitTestResult temp_result(result.GetHitTestRequest(),
                              recursion_data.original_location);
    bool inside_fragment_background_rect = false;
    if (HitTestContentsForFragments(*layer_fragments, offset, temp_result,
                                    recursion_data.location, kHitTestSelf,
                                    inside_fragment_background_rect) &&
        IsHitCandidate(this, false, z_offset_for_contents_ptr,
                       unflattened_transform_state)) {
      if (result.GetHitTestRequest().ListBased())
        result.Append(temp_result);
      else
        result = temp_result;
      return this;
    }
    if (inside_fragment_background_rect &&
        result.GetHitTestRequest().ListBased())
      result.Append(temp_result);
  }

  return nullptr;
}

bool PaintLayer::HitTestContentsForFragments(
    const PaintLayerFragments& layer_fragments,
    const LayoutPoint& offset,
    HitTestResult& result,
    const HitTestLocation& hit_test_location,
    HitTestFilter hit_test_filter,
    bool& inside_clip_rect) const {
  if (layer_fragments.IsEmpty())
    return false;

  for (int i = layer_fragments.size() - 1; i >= 0; --i) {
    const PaintLayerFragment& fragment = layer_fragments.at(i);
    if ((hit_test_filter == kHitTestSelf &&
         !fragment.background_rect.Intersects(hit_test_location)) ||
        (hit_test_filter == kHitTestDescendants &&
         !fragment.foreground_rect.Intersects(hit_test_location)))
      continue;
    inside_clip_rect = true;
    LayoutPoint fragment_offset = offset;
    fragment_offset.MoveBy(fragment.layer_bounds.Location());
    if (HitTestContents(result, fragment_offset, hit_test_location,
                        hit_test_filter))
      return true;
  }

  return false;
}

PaintLayer* PaintLayer::HitTestTransformedLayerInFragments(
    PaintLayer* root_layer,
    PaintLayer* container_layer,
    HitTestResult& result,
    const HitTestRecursionData& recursion_data,
    HitTestingTransformState* transform_state,
    double* z_offset,
    ShouldRespectOverflowClipType clip_behavior) {
  PaintLayerFragments enclosing_pagination_fragments;
  // FIXME: We're missing a sub-pixel offset here crbug.com/348728

  EnclosingPaginationLayer()->CollectFragments(
      enclosing_pagination_fragments, root_layer, nullptr,
      kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, nullptr,
      LayoutSize());

  for (const auto& fragment : enclosing_pagination_fragments) {
    // Apply the page/column clip for this fragment, as well as any clips
    // established by layers in between us and the enclosing pagination layer.
    LayoutRect clip_rect = fragment.background_rect.Rect();
    if (!recursion_data.location.Intersects(clip_rect))
      continue;

    PaintLayer* hit_layer = HitTestLayerByApplyingTransform(
        root_layer, container_layer, result, recursion_data, transform_state,
        z_offset, fragment.fragment_data->PaginationOffset());
    if (hit_layer)
      return hit_layer;
  }

  return nullptr;
}

PaintLayer* PaintLayer::HitTestLayerByApplyingTransform(
    PaintLayer* root_layer,
    PaintLayer* container_layer,
    HitTestResult& result,
    const HitTestRecursionData& recursion_data,
    HitTestingTransformState* transform_state,
    double* z_offset,
    const LayoutPoint& translation_offset) {
  // Create a transform state to accumulate this transform.
  HitTestingTransformState new_transform_state =
      CreateLocalTransformState(root_layer, container_layer, recursion_data,
                                transform_state, translation_offset);

  // If the transform can't be inverted, then don't hit test this layer at all.
  if (!new_transform_state.accumulated_transform_.IsInvertible())
    return nullptr;

  // Compute the point and the hit test rect in the coords of this layer by
  // using the values from the transformState, which store the point and quad in
  // the coords of the last flattened layer, and the accumulated transform which
  // lets up map through preserve-3d layers.
  //
  // We can't just map hitTestLocation and hitTestRect because they may have
  // been flattened (losing z) by our container.
  FloatPoint local_point = new_transform_state.MappedPoint();
  FloatQuad local_point_quad = new_transform_state.MappedQuad();
  LayoutRect bounds_of_mapped_area = new_transform_state.BoundsOfMappedArea();
  base::Optional<HitTestLocation> new_location;
  if (recursion_data.location.IsRectBasedTest())
    new_location.emplace(local_point, local_point_quad);
  else
    new_location.emplace(local_point);
  HitTestRecursionData new_recursion_data(bounds_of_mapped_area, *new_location,
                                          recursion_data.original_location);

  // Now do a hit test with the root layer shifted to be us.
  return HitTestLayer(this, container_layer, result, new_recursion_data, true,
                      &new_transform_state, z_offset);
}

bool PaintLayer::HitTestContents(HitTestResult& result,
                                 const LayoutPoint& fragment_offset,
                                 const HitTestLocation& hit_test_location,
                                 HitTestFilter hit_test_filter) const {
  DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant());
  if (!GetLayoutObject().HitTestAllPhases(result, hit_test_location,
                                          fragment_offset, hit_test_filter)) {
    // It's wrong to set innerNode, but then claim that you didn't hit anything,
    // unless it is a list-based test.
    DCHECK(!result.InnerNode() || (result.GetHitTestRequest().ListBased() &&
                                   result.ListBasedTestResult().size()));
    return false;
  }

  if (!result.InnerNode()) {
    // We hit something anonymous, and we didn't find a DOM node ancestor in
    // this layer.

    if (GetLayoutObject().IsLayoutFlowThread()) {
      // For a flow thread it's safe to just say that we didn't hit anything.
      // That means that we'll continue as normally, and eventually hit a column
      // set sibling instead. Column sets are also anonymous, but, unlike flow
      // threads, they don't establish layers, so we'll fall back and hit the
      // multicol container parent (which should have a DOM node).
      return false;
    }

    Node* e = EnclosingNode();
    // FIXME: should be a call to result.setNodeAndPosition. What we would
    // really want to do here is to return and look for the nearest
    // non-anonymous ancestor, and ignore aunts and uncles on our way. It's bad
    // to look for it manually like we do here, and give up on setting a local
    // point in the result, because that has bad implications for text selection
    // and caretRangeFromPoint(). See crbug.com/461791
    // This code path only ever hits in fullscreen tests.
    result.SetInnerNode(e);
  }
  return true;
}

bool PaintLayer::IsReplacedNormalFlowStacking() const {
  return GetLayoutObject().IsSVGForeignObject();
}

void PaintLayer::SetNeedsCompositingLayerAssignment() {
  needs_compositing_layer_assignment_ = true;

  for (PaintLayer* curr = CompositingContainer();
       curr && !curr->StackingDescendantNeedsCompositingLayerAssignment();
       curr = curr->CompositingContainer()) {
    curr->descendant_needs_compositing_layer_assignment_ = true;
  }
}

void PaintLayer::ClearNeedsCompositingLayerAssignment() {
  needs_compositing_layer_assignment_ = false;
  descendant_needs_compositing_layer_assignment_ = false;
}

void PaintLayer::SetNeedsCompositingRequirementsUpdate() {
  for (PaintLayer* curr = this;
       curr && !curr->DescendantMayNeedCompositingRequirementsUpdate();
       curr = curr->Parent()) {
    curr->descendant_may_need_compositing_requirements_update_ = true;
  }
}

PaintLayer* PaintLayer::HitTestChildren(
    ChildrenIteration childrento_visit,
    PaintLayer* root_layer,
    HitTestResult& result,
    const HitTestRecursionData& recursion_data,
    HitTestingTransformState* transform_state,
    double* z_offset_for_descendants,
    double* z_offset,
    HitTestingTransformState* unflattened_transform_state,
    bool depth_sort_descendants) {
  if (!HasSelfPaintingLayerDescendant())
    return nullptr;

  if (!stacking_node_)
    return nullptr;

  const LayoutObject* stop_node = result.GetHitTestRequest().GetStopNode();
  PaintLayer* stop_layer = stop_node ? stop_node->PaintingLayer() : nullptr;

  PaintLayer* result_layer = nullptr;
  PaintLayerStackingNodeReverseIterator iterator(*stacking_node_,
                                                 childrento_visit);
  while (PaintLayer* child_layer = iterator.Next()) {
    if (child_layer->IsReplacedNormalFlowStacking())
      continue;

    // Calling IsDescendantOf is sad (slow), but it's the only way to tell
    // whether the child layer is a descendant of the stop node.
    if (stop_layer == this &&
        child_layer->GetLayoutObject().IsDescendantOf(stop_node)) {
      continue;
    }

    PaintLayer* hit_layer = nullptr;
    HitTestResult temp_result(result.GetHitTestRequest(),
                              recursion_data.original_location);
    hit_layer = child_layer->HitTestLayer(
        root_layer, this, temp_result, recursion_data, false, transform_state,
        z_offset_for_descendants);

    // If it is a list-based test, we can safely append the temporary result
    // since it might had hit nodes but not necesserily had hitLayer set.
    if (result.GetHitTestRequest().ListBased())
      result.Append(temp_result);

    if (IsHitCandidate(hit_layer, depth_sort_descendants, z_offset,
                       unflattened_transform_state)) {
      result_layer = hit_layer;
      if (!result.GetHitTestRequest().ListBased())
        result = temp_result;
      if (!depth_sort_descendants)
        break;
    }
  }

  return result_layer;
}

void PaintLayer::UpdateFilterReferenceBox() {
  if (!NeedsFilterReferenceBox())
    return;
  FloatRect reference_box =
      FloatRect(PhysicalBoundingBoxIncludingStackingChildren(
          LayoutPoint(),
          PaintLayer::kIncludeTransformsAndCompositedChildLayers));
  float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
  if (zoom != 1)
    reference_box.Scale(1 / zoom);
  EnsureResourceInfo().SetFilterReferenceBox(reference_box);
}

bool PaintLayer::NeedsFilterReferenceBox() const {
  if (GetLayoutObject().HasReflection() && GetLayoutObject().IsBox())
    return true;
  FilterOperations operations = GetLayoutObject().StyleRef().Filter();
  if (operations.HasBlurOrReferenceFilter())
    return true;
  operations = GetLayoutObject().StyleRef().BackdropFilter();
  return !operations.IsEmpty();
}

FloatRect PaintLayer::FilterReferenceBox() const {
  DCHECK(IsAllowedToQueryCompositingState());
  if (ResourceInfo())
    return ResourceInfo()->FilterReferenceBox();
  return FloatRect();
}

FloatRect PaintLayer::BackdropFilterReferenceBox() const {
  FloatRect reference_box(GetLayoutObject().BorderBoundingBox());
  float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
  if (zoom != 1)
    reference_box.Scale(1 / zoom);
  reference_box.Move(-ToFloatSize(FilterReferenceBox().Location()));
  return reference_box;
}

gfx::RRectF PaintLayer::BackdropFilterBounds(
    const FloatRect& reference_box) const {
  auto& style = GetLayoutObject().StyleRef();
  if (!style.HasBorderRadius())
    return gfx::RRectF(reference_box, 0);
  FloatRoundedRect rrect = style.GetRoundedBorderFor(LayoutRect(reference_box));
  // FloatRoundedRect has a typecast to SkRRect().
  return gfx::RRectF(rrect);
}

bool PaintLayer::HitTestClippedOutByClipPath(
    PaintLayer* root_layer,
    const HitTestLocation& hit_test_location) const {
  DCHECK(GetLayoutObject().HasClipPath());
  DCHECK(IsSelfPaintingLayer());
  DCHECK(root_layer);

  LayoutRect origin;
  if (EnclosingPaginationLayer())
    ConvertFromFlowThreadToVisualBoundingBoxInAncestor(root_layer, origin);
  else
    ConvertToLayerCoords(root_layer, origin);

  FloatPoint point(hit_test_location.Point() - origin.Location());
  FloatRect reference_box(
      ClipPathClipper::LocalReferenceBox(GetLayoutObject()));

  ClipPathOperation* clip_path_operation =
      GetLayoutObject().StyleRef().ClipPath();
  DCHECK(clip_path_operation);
  if (clip_path_operation->GetType() == ClipPathOperation::SHAPE) {
    ShapeClipPathOperation* clip_path =
        ToShapeClipPathOperation(clip_path_operation);
    return !clip_path->GetPath(reference_box).Contains(point);
  }
  DCHECK_EQ(clip_path_operation->GetType(), ClipPathOperation::REFERENCE);
  SVGResource* resource =
      ToReferenceClipPathOperation(*clip_path_operation).Resource();
  LayoutSVGResourceContainer* container =
      resource ? resource->ResourceContainer() : nullptr;
  if (!container || container->ResourceType() != kClipperResourceType)
    return false;
  auto* clipper = ToLayoutSVGResourceClipper(container);
  // If the clipPath is using "userspace on use" units, then the origin of
  // the coordinate system is the top-left of the reference box, so adjust
  // the point accordingly.
  if (clipper->ClipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse)
    point.MoveBy(-reference_box.Location());
  // Unzoom the point and the reference box, since the <clipPath> geometry is
  // not zoomed.
  float inverse_zoom = 1 / GetLayoutObject().StyleRef().EffectiveZoom();
  point.Scale(inverse_zoom, inverse_zoom);
  reference_box.Scale(inverse_zoom);
  HitTestLocation location(point);
  return !clipper->HitTestClipContent(reference_box, location);
}

bool PaintLayer::IntersectsDamageRect(
    const LayoutRect& layer_bounds,
    const LayoutRect& damage_rect,
    const LayoutPoint& offset_from_root) const {
  // Always examine the canvas and the root.
  // FIXME: Could eliminate the isDocumentElement() check if we fix background
  // painting so that the LayoutView paints the root's background.
  if (IsRootLayer() || GetLayoutObject().IsDocumentElement())
    return true;

  // If we aren't an inline flow, and our layer bounds do intersect the damage
  // rect, then we can go ahead and return true.
  LayoutView* view = GetLayoutObject().View();
  DCHECK(view);
  if (view && !GetLayoutObject().IsLayoutInline()) {
    if (layer_bounds.Intersects(damage_rect))
      return true;
  }

  // Otherwise we need to compute the bounding box of this single layer and see
  // if it intersects the damage rect.
  return PhysicalBoundingBox(offset_from_root).Intersects(damage_rect);
}

LayoutRect PaintLayer::LogicalBoundingBox() const {
  LayoutRect rect = GetLayoutObject().VisualOverflowRect();

  if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) {
    rect.Unite(LayoutRect(rect.Location(),
                          GetLayoutObject().View()->ViewRect().Size()));
  }

  return rect;
}

static inline LayoutRect FlippedLogicalBoundingBox(
    LayoutRect bounding_box,
    LayoutObject& layout_object) {
  LayoutRect result = bounding_box;
  if (layout_object.IsBox())
    ToLayoutBox(layout_object).FlipForWritingMode(result);
  else
    layout_object.ContainingBlock()->FlipForWritingMode(result);
  return result;
}

LayoutRect PaintLayer::PhysicalBoundingBox(
    const PaintLayer* ancestor_layer) const {
  LayoutPoint offset_from_root;
  ConvertToLayerCoords(ancestor_layer, offset_from_root);
  return PhysicalBoundingBox(offset_from_root);
}

LayoutRect PaintLayer::PhysicalBoundingBox(
    const LayoutPoint& offset_from_root) const {
  LayoutRect result =
      FlippedLogicalBoundingBox(LogicalBoundingBox(), GetLayoutObject());
  result.MoveBy(offset_from_root);
  return result;
}

LayoutRect PaintLayer::FragmentsBoundingBox(
    const PaintLayer* ancestor_layer) const {
  if (!EnclosingPaginationLayer())
    return PhysicalBoundingBox(ancestor_layer);

  LayoutRect result =
      FlippedLogicalBoundingBox(LogicalBoundingBox(), GetLayoutObject());
  ConvertFromFlowThreadToVisualBoundingBoxInAncestor(ancestor_layer, result);
  return result;
}

LayoutRect PaintLayer::BoundingBoxForCompositingOverlapTest() const {
  // Apply NeverIncludeTransformForAncestorLayer, because the geometry map in
  // CompositingInputsUpdater will take care of applying the transform of |this|
  // (== the ancestorLayer argument to boundingBoxForCompositing).
  // TODO(trchen): Layer fragmentation is inhibited across compositing boundary.
  // Should we return the unfragmented bounds for overlap testing? Or perhaps
  // assume fragmented layers always overlap?
  return OverlapBoundsIncludeChildren()
             ? BoundingBoxForCompositingInternal(
                   *this, nullptr, kNeverIncludeTransformForAncestorLayer)
             : FragmentsBoundingBox(this);
}

bool PaintLayer::OverlapBoundsIncludeChildren() const {
  return HasFilterThatMovesPixels();
}

void PaintLayer::ExpandRectForStackingChildren(
    const PaintLayer& composited_layer,
    LayoutRect& result,
    PaintLayer::CalculateBoundsOptions options) const {
  if (!StackingNode())
    return;

  DCHECK(GetLayoutObject().StyleRef().IsStackingContext() ||
         !StackingNode()->HasPositiveZOrderList());

#if DCHECK_IS_ON()
  LayerListMutationDetector mutation_checker(
      const_cast<PaintLayer*>(this)->StackingNode());
#endif

  PaintLayerStackingNodeIterator iterator(*StackingNode(), kAllChildren);
  while (PaintLayer* child_layer = iterator.Next()) {
    // Here we exclude both directly composited layers and squashing layers
    // because those Layers don't paint into the graphics layer
    // for this Layer. For example, the bounds of squashed Layers
    // will be included in the computation of the appropriate squashing
    // GraphicsLayer.
    if (options != PaintLayer::CalculateBoundsOptions::
                       kIncludeTransformsAndCompositedChildLayers &&
        child_layer->GetCompositingState() != kNotComposited)
      continue;
    result.Unite(child_layer->BoundingBoxForCompositingInternal(
        composited_layer, this, options));
  }
}

LayoutRect PaintLayer::PhysicalBoundingBoxIncludingStackingChildren(
    const LayoutPoint& offset_from_root,
    CalculateBoundsOptions options) const {
  LayoutRect result = PhysicalBoundingBox(LayoutPoint());
  ExpandRectForStackingChildren(*this, result, options);

  result.MoveBy(offset_from_root);
  return result;
}

LayoutRect PaintLayer::BoundingBoxForCompositing() const {
  return BoundingBoxForCompositingInternal(
      *this, nullptr, kMaybeIncludeTransformForAncestorLayer);
}

LayoutRect PaintLayer::BoundingBoxForCompositingInternal(
    const PaintLayer& composited_layer,
    const PaintLayer* stacking_parent,
    CalculateBoundsOptions options) const {
  if (!IsSelfPaintingLayer())
    return LayoutRect();

  // FIXME: This could be improved to do a check like
  // hasVisibleNonCompositingDescendantLayers() (bug 92580).
  if (this != &composited_layer && !HasVisibleContent() &&
      !HasVisibleDescendant())
    return LayoutRect();

  if (GetLayoutObject().IsEffectiveRootScroller() || IsRootLayer()) {
    // In root layer scrolling mode, the main GraphicsLayer is the size of the
    // layout viewport. In non-RLS mode, it is the union of the layout viewport
    // and the document's layout overflow rect.
    IntRect result = IntRect();
    if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
      result = IntRect(IntPoint(), frame_view->Size());
    return LayoutRect(result);
  }

  // The layer created for the LayoutFlowThread is just a helper for painting
  // and hit-testing, and should not contribute to the bounding box. The
  // LayoutMultiColumnSets will contribute the correct size for the layout
  // content of the multicol container.
  if (GetLayoutObject().IsLayoutFlowThread())
    return LayoutRect();

  // If there is a clip applied by an ancestor to this PaintLayer but below or
  // equal to |ancestorLayer|, apply that clip.
  LayoutRect result = Clipper(GeometryMapperOption::kDoNotUseGeometryMapper)
                          .LocalClipRect(composited_layer);

  result.Intersect(PhysicalBoundingBox(LayoutPoint()));

  ExpandRectForStackingChildren(composited_layer, result, options);

  // Only enlarge by the filter outsets if we know the filter is going to be
  // rendered in software.  Accelerated filters will handle their own outsets.
  if (PaintsWithFilters())
    result = MapLayoutRectForFilter(result);

  if (Transform() && (options == kIncludeTransformsAndCompositedChildLayers ||
                      ((PaintsWithTransform(kGlobalPaintNormalPhase) &&
                        (this != &composited_layer ||
                         options == kMaybeIncludeTransformForAncestorLayer)))))
    result = Transform()->MapRect(result);

  if (ShouldFragmentCompositedBounds(&composited_layer)) {
    ConvertFromFlowThreadToVisualBoundingBoxInAncestor(&composited_layer,
                                                       result);
    return result;
  }

  if (stacking_parent) {
    LayoutPoint delta;
    ConvertToLayerCoords(stacking_parent, delta);
    result.MoveBy(delta);
  }
  return result;
}

CompositingState PaintLayer::GetCompositingState() const {
  DCHECK(IsAllowedToQueryCompositingState());

  // This is computed procedurally so there is no redundant state variable that
  // can get out of sync from the real actual compositing state.

  if (GroupedMapping()) {
    DCHECK(!GetCompositedLayerMapping());
    return kPaintsIntoGroupedBacking;
  }

  if (!GetCompositedLayerMapping())
    return kNotComposited;

  return kPaintsIntoOwnBacking;
}

bool PaintLayer::IsAllowedToQueryCompositingState() const {
  if (g_compositing_query_mode == kCompositingQueriesAreAllowed ||
      RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
    return true;
  return GetLayoutObject().GetDocument().Lifecycle().GetState() >=
         DocumentLifecycle::kInCompositingUpdate;
}

CompositedLayerMapping* PaintLayer::GetCompositedLayerMapping() const {
  DCHECK(IsAllowedToQueryCompositingState());
  return rare_data_ ? rare_data_->composited_layer_mapping.get() : nullptr;
}

GraphicsLayer* PaintLayer::GraphicsLayerBacking(const LayoutObject* obj) const {
  switch (GetCompositingState()) {
    case kNotComposited:
      return nullptr;
    case kPaintsIntoGroupedBacking:
      return GroupedMapping()->SquashingLayer();
    default:
      return (obj != &GetLayoutObject() &&
              GetCompositedLayerMapping()->ScrollingContentsLayer())
                 ? GetCompositedLayerMapping()->ScrollingContentsLayer()
                 : GetCompositedLayerMapping()->MainGraphicsLayer();
  }
}

void PaintLayer::EnsureCompositedLayerMapping() {
  if (rare_data_ && rare_data_->composited_layer_mapping)
    return;

  EnsureRareData().composited_layer_mapping =
      std::make_unique<CompositedLayerMapping>(*this);
  rare_data_->composited_layer_mapping->SetNeedsGraphicsLayerUpdate(
      kGraphicsLayerUpdateSubtree);
}

void PaintLayer::ClearCompositedLayerMapping(bool layer_being_destroyed) {
  if (!layer_being_destroyed) {
    // We need to make sure our decendants get a geometry update. In principle,
    // we could call setNeedsGraphicsLayerUpdate on our children, but that would
    // require walking the z-order lists to find them. Instead, we
    // over-invalidate by marking our parent as needing a geometry update.
    if (PaintLayer* compositing_parent =
            EnclosingLayerWithCompositedLayerMapping(kExcludeSelf))
      compositing_parent->GetCompositedLayerMapping()
          ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
  }

  if (rare_data_)
    rare_data_->composited_layer_mapping.reset();
}

void PaintLayer::SetGroupedMapping(CompositedLayerMapping* grouped_mapping,
                                   SetGroupMappingOptions options) {
  CompositedLayerMapping* old_grouped_mapping = GroupedMapping();
  if (grouped_mapping == old_grouped_mapping)
    return;

  if (options == kInvalidateLayerAndRemoveFromMapping && old_grouped_mapping) {
    old_grouped_mapping->SetNeedsGraphicsLayerUpdate(
        kGraphicsLayerUpdateSubtree);
    old_grouped_mapping->RemoveLayerFromSquashingGraphicsLayer(this);
  }
  if (rare_data_ || grouped_mapping)
    EnsureRareData().grouped_mapping = grouped_mapping;
#if DCHECK_IS_ON()
  DCHECK(!grouped_mapping ||
         grouped_mapping->VerifyLayerInSquashingVector(this));
#endif
  if (options == kInvalidateLayerAndRemoveFromMapping && grouped_mapping)
    grouped_mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
}

bool PaintLayer::NeedsCompositedScrolling() const {
  return scrollable_area_ && scrollable_area_->NeedsCompositedScrolling();
}

bool PaintLayer::PaintsWithTransform(
    GlobalPaintFlags global_paint_flags) const {
  return Transform() && !PaintsIntoOwnBacking(global_paint_flags);
}

bool PaintLayer::PaintsIntoOwnBacking(
    GlobalPaintFlags global_paint_flags) const {
  return !(global_paint_flags & kGlobalPaintFlattenCompositingLayers) &&
         GetCompositingState() == kPaintsIntoOwnBacking;
}

bool PaintLayer::PaintsIntoOwnOrGroupedBacking(
    GlobalPaintFlags global_paint_flags) const {
  return !(global_paint_flags & kGlobalPaintFlattenCompositingLayers) &&
         GetCompositingState() != kNotComposited;
}

bool PaintLayer::SupportsSubsequenceCaching() const {
  if (EnclosingPaginationLayer())
    return false;

  // SVG paints atomically.
  if (GetLayoutObject().IsSVGRoot())
    return true;

  // Create subsequence for only stacking contexts whose painting are atomic.
  return GetLayoutObject().StyleRef().IsStackingContext();
}

ScrollingCoordinator* PaintLayer::GetScrollingCoordinator() {
  Page* page = GetLayoutObject().GetFrame()->GetPage();
  return (!page) ? nullptr : page->GetScrollingCoordinator();
}

bool PaintLayer::CompositesWithTransform() const {
  return TransformAncestor() || Transform();
}

bool PaintLayer::CompositesWithOpacity() const {
  return OpacityAncestor() || GetLayoutObject().StyleRef().HasOpacity();
}

bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
    const LayoutRect& local_rect,
    bool should_check_children) const {
  if (PaintsWithTransparency(kGlobalPaintNormalPhase))
    return false;

  // We can't use hasVisibleContent(), because that will be true if our
  // layoutObject is hidden, but some child is visible and that child doesn't
  // cover the entire rect.
  if (GetLayoutObject().StyleRef().Visibility() != EVisibility::kVisible)
    return false;

  if (GetLayoutObject().HasMask() || GetLayoutObject().HasClipPath())
    return false;

  if (PaintsWithFilters() &&
      GetLayoutObject().StyleRef().Filter().HasFilterThatAffectsOpacity())
    return false;

  // FIXME: Handle simple transforms.
  if (Transform() && GetCompositingState() != kPaintsIntoOwnBacking)
    return false;

  if (GetLayoutObject().StyleRef().GetPosition() == EPosition::kFixed &&
      GetCompositingState() != kPaintsIntoOwnBacking)
    return false;

  // FIXME: We currently only check the immediate layoutObject,
  // which will miss many cases where additional layout objects paint
  // into this layer.
  if (GetLayoutObject().BackgroundIsKnownToBeOpaqueInRect(local_rect))
    return true;

  if (!should_check_children)
    return false;

  // We can't consult child layers if we clip, since they might cover
  // parts of the rect that are clipped out.
  if (GetLayoutObject().HasClipRelatedProperty())
    return false;

  // TODO(schenney): This could be improved by unioning the opaque regions of
  // all the children.  That would require a refactoring because currently
  // children just check they at least cover the given rect, but a unioning
  // method would require children to compute and report their rects.
  return ChildBackgroundIsKnownToBeOpaqueInRect(local_rect);
}

bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
    const LayoutRect& local_rect) const {
  if (!stacking_node_)
    return false;

  PaintLayerStackingNodeReverseIterator reverse_iterator(
      *stacking_node_,
      kPositiveZOrderChildren | kNormalFlowChildren | kNegativeZOrderChildren);
  while (PaintLayer* child_layer = reverse_iterator.Next()) {
    // Stop at composited paint boundaries and non-self-painting layers.
    if (child_layer->IsPaintInvalidationContainer())
      continue;

    if (!child_layer->CanUseConvertToLayerCoords())
      continue;

    LayoutPoint child_offset;
    LayoutRect child_local_rect(local_rect);
    child_layer->ConvertToLayerCoords(this, child_offset);
    child_local_rect.MoveBy(-child_offset);

    if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect, true))
      return true;
  }
  return false;
}

bool PaintLayer::ShouldBeSelfPaintingLayer() const {
  // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
  // main-thread AnimationWorklet and don't need to promote the scroll-source.
  return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
         (scrollable_area_ && scrollable_area_->HasOverlayScrollbars()) ||
         ScrollsOverflow() ||
         ScrollTimeline::HasActiveScrollTimeline(GetLayoutObject().GetNode());
}

void PaintLayer::UpdateSelfPaintingLayer() {
  bool is_self_painting_layer = ShouldBeSelfPaintingLayer();
  if (IsSelfPaintingLayer() == is_self_painting_layer)
    return;

  // Invalidate the old subsequences which may no longer contain some
  // descendants of this layer because of the self painting status change.
  SetNeedsRepaint();
  is_self_painting_layer_ = is_self_painting_layer;
  self_painting_status_changed_ = true;
  // Self-painting change can change the compositing container chain;
  // invalidate the new chain in addition to the old one.
  MarkCompositingContainerChainForNeedsRepaint();

  if (is_self_painting_layer)
    SetNeedsVisualOverflowRecalc();

  if (PaintLayer* parent = Parent()) {
    parent->MarkAncestorChainForFlagsUpdate();

    if (PaintLayer* enclosing_self_painting_layer =
            parent->EnclosingSelfPaintingLayer()) {
      if (is_self_painting_layer)
        MergeNeedsPaintPhaseFlagsFrom(*enclosing_self_painting_layer);
      else
        enclosing_self_painting_layer->MergeNeedsPaintPhaseFlagsFrom(*this);
    }
  }
}

PaintLayer* PaintLayer::EnclosingSelfPaintingLayer() {
  PaintLayer* layer = this;
  while (layer && !layer->IsSelfPaintingLayer())
    layer = layer->Parent();
  return layer;
}

bool PaintLayer::HasNonEmptyChildLayoutObjects() const {
  // Some HTML can cause whitespace text nodes to have layoutObjects, like:
  // <div>
  // <img src=...>
  // </div>
  // so test for 0x0 LayoutTexts here
  for (LayoutObject* child = GetLayoutObject().SlowFirstChild(); child;
       child = child->NextSibling()) {
    if (!child->HasLayer()) {
      if (child->IsLayoutInline() || !child->IsBox())
        return true;

      if (ToLayoutBox(child)->Size().Width() > 0 ||
          ToLayoutBox(child)->Size().Height() > 0)
        return true;
    }
  }
  return false;
}

bool PaintLayer::HasBoxDecorationsOrBackground() const {
  return GetLayoutObject().StyleRef().HasBoxDecorations() ||
         GetLayoutObject().StyleRef().HasBackground();
}

bool PaintLayer::HasVisibleBoxDecorations() const {
  if (!HasVisibleContent())
    return false;

  return HasBoxDecorationsOrBackground() || HasOverflowControls();
}

void PaintLayer::UpdateFilters(const ComputedStyle* old_style,
                               const ComputedStyle& new_style) {
  if (!filter_on_effect_node_dirty_) {
    filter_on_effect_node_dirty_ =
        old_style ? !old_style->FilterDataEquivalent(new_style) ||
                        !old_style->ReflectionDataEquivalent(new_style)
                  : new_style.HasFilterInducingProperty();
  }

  if (!new_style.HasFilterInducingProperty() &&
      (!old_style || !old_style->HasFilterInducingProperty()))
    return;

  const bool had_resource_info = ResourceInfo();
  if (new_style.HasFilterInducingProperty())
    new_style.Filter().AddClient(EnsureResourceInfo());
  if (had_resource_info && old_style)
    old_style->Filter().RemoveClient(*ResourceInfo());
}

void PaintLayer::UpdateClipPath(const ComputedStyle* old_style,
                                const ComputedStyle& new_style) {
  ClipPathOperation* new_clip = new_style.ClipPath();
  ClipPathOperation* old_clip = old_style ? old_style->ClipPath() : nullptr;
  if (!new_clip && !old_clip)
    return;
  const bool had_resource_info = ResourceInfo();
  if (auto* reference_clip = ToReferenceClipPathOperationOrNull(new_clip))
    reference_clip->AddClient(EnsureResourceInfo());
  if (had_resource_info) {
    if (auto* old_reference_clip = ToReferenceClipPathOperationOrNull(old_clip))
      old_reference_clip->RemoveClient(*ResourceInfo());
  }
}

bool PaintLayer::AttemptDirectCompositingUpdate(
    const StyleDifference& diff,
    const ComputedStyle* old_style) {
  CompositingReasons old_potential_compositing_reasons_from_style =
      PotentialCompositingReasonsFromStyle();
  if (Compositor() &&
      (diff.HasDifference() || needs_compositing_reasons_update_))
    Compositor()->UpdatePotentialCompositingReasonsFromStyle(*this);
  needs_compositing_reasons_update_ = false;

  // This function implements an optimization for transforms and opacity.
  // A common pattern is for a touchmove handler to update the transform
  // and/or an opacity of an element every frame while the user moves their
  // finger across the screen. The conditions below recognize when the
  // compositing state is set up to receive a direct transform or opacity
  // update.

  if (!diff.HasAtMostPropertySpecificDifferences(
          StyleDifference::kTransformChanged |
          StyleDifference::kOpacityChanged))
    return false;
  // The potentialCompositingReasonsFromStyle could have changed without
  // a corresponding StyleDifference if an animation started or ended.
  if (PotentialCompositingReasonsFromStyle() !=
      old_potential_compositing_reasons_from_style)
    return false;
  if (!rare_data_ || !rare_data_->composited_layer_mapping)
    return false;

  // If a transform changed, we can't use the fast path.
  if (diff.TransformChanged())
    return false;

  // We composite transparent Layers differently from non-transparent
  // Layers even when the non-transparent Layers are already a
  // stacking context.
  if (diff.OpacityChanged() &&
      layout_object_.StyleRef().HasOpacity() != old_style->HasOpacity())
    return false;

  // Changes in pointer-events affect hit test visibility of the scrollable
  // area and its |m_scrollsOverflow| value which determines if the layer
  // requires composited scrolling or not.
  if (scrollable_area_ &&
      layout_object_.StyleRef().PointerEvents() != old_style->PointerEvents())
    return false;

  UpdateTransform(old_style, GetLayoutObject().StyleRef());

  // FIXME: Consider introducing a smaller graphics layer update scope
  // that just handles transforms and opacity. GraphicsLayerUpdateLocal
  // will also program bounds, clips, and many other properties that could
  // not possibly have changed.
  rare_data_->composited_layer_mapping->SetNeedsGraphicsLayerUpdate(
      kGraphicsLayerUpdateLocal);
  if (Compositor()) {
    Compositor()->SetNeedsCompositingUpdate(
        kCompositingUpdateAfterGeometryChange);
  }

  if (RequiresScrollableArea()) {
    DCHECK(scrollable_area_);
    scrollable_area_->UpdateAfterStyleChange(old_style);
  }

  return true;
}

void PaintLayer::StyleDidChange(StyleDifference diff,
                                const ComputedStyle* old_style) {
  UpdateScrollableArea();

  if (AttemptDirectCompositingUpdate(diff, old_style)) {
    if (diff.HasDifference())
      GetLayoutObject().SetNeedsPaintPropertyUpdate();
    return;
  }

  if (PaintLayerStackingNode::StyleDidChange(this, old_style))
    MarkAncestorChainForFlagsUpdate();

  if (RequiresScrollableArea()) {
    DCHECK(scrollable_area_);
    scrollable_area_->UpdateAfterStyleChange(old_style);
  }

  // Overlay scrollbars can make this layer self-painting so we need
  // to recompute the bit once scrollbars have been updated.
  UpdateSelfPaintingLayer();

  const ComputedStyle& new_style = GetLayoutObject().StyleRef();

  if (diff.CompositingReasonsChanged()) {
    SetNeedsCompositingInputsUpdate();
  } else {
    // For querying stale GetCompositingState().
    DisableCompositingQueryAsserts disable;

    // Compositing inputs update is required when the PaintLayer is currently
    // composited. This is because even style changes as simple as background
    // color change, or pointer-events state change, can update compositing
    // state.
    if (old_style && GetCompositingState() == kPaintsIntoOwnBacking)
      SetNeedsCompositingInputsUpdate();
  }

  // HasAlphaChanged can affect whether a composited layer is opaque.
  if (diff.NeedsLayout() || diff.HasAlphaChanged())
    SetNeedsCompositingInputsUpdate();

  // A scroller that changes background color might become opaque or not
  // opaque, which in turn affects whether it can be composited on low-DPI
  // screens.
  if (GetScrollableArea() && GetScrollableArea()->ScrollsOverflow() &&
      diff.HasDifference()) {
    SetNeedsCompositingInputsUpdate();
  }

  if (diff.TransformChanged() || diff.OpacityChanged() ||
      diff.ZIndexChanged() || diff.FilterChanged() ||
      diff.BackdropFilterChanged() || diff.CssClipChanged() ||
      diff.BlendModeChanged() || diff.MaskChanged()) {
    GetLayoutObject().SetNeedsPaintPropertyUpdate();
    SetNeedsCompositingInputsUpdate();
  }

  // HasNonContainedAbsolutePositionDescendant depends on position changes.
  if (!old_style || old_style->GetPosition() != new_style.GetPosition())
    MarkAncestorChainForFlagsUpdate();

  UpdateTransform(old_style, new_style);
  UpdateFilters(old_style, new_style);
  UpdateClipPath(old_style, new_style);

  if (!NeedsRepaint()) {
    if (diff.ZIndexChanged()) {
      // We don't need to invalidate paint of objects when paint order
      // changes. However, we do need to repaint the containing stacking
      // context, in order to generate new paint chunks in the correct order.
      // Raster invalidation will be issued if needed during paint.
      SetNeedsRepaint();
    } else if (old_style &&
               !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
      // Change of PaintedOutputInvisible() will affect existence of paint
      // chunks, so needs repaint.
      if (PaintLayerPainter::PaintedOutputInvisible(*old_style) !=
          PaintLayerPainter::PaintedOutputInvisible(new_style))
        SetNeedsRepaint();
    }
  }
}

LayoutPoint PaintLayer::LocationInternal() const {
  LayoutPoint result(location_);
  PaintLayer* containing_layer = ContainingLayer();
  if (containing_layer && containing_layer->IsRootLayer() &&
      containing_layer->GetLayoutObject().HasOverflowClip()) {
    result -= containing_layer->GetLayoutBox()->ScrolledContentOffset();
  }
  return result;
}

PaintLayerClipper PaintLayer::Clipper(
    GeometryMapperOption geometry_mapper_option) const {
  return PaintLayerClipper(*this, geometry_mapper_option ==
                                      GeometryMapperOption::kUseGeometryMapper);
}

bool PaintLayer::ScrollsOverflow() const {
  if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea())
    return scrollable_area->ScrollsOverflow();

  return false;
}

FilterOperations PaintLayer::FilterOperationsIncludingReflection() const {
  const auto& style = GetLayoutObject().StyleRef();
  FilterOperations filter_operations = style.Filter();
  if (GetLayoutObject().HasReflection() && GetLayoutObject().IsBox()) {
    BoxReflection reflection = BoxReflectionForPaintLayer(*this, style);
    filter_operations.Operations().push_back(
        BoxReflectFilterOperation::Create(reflection));
  }
  return filter_operations;
}

void PaintLayer::UpdateCompositorFilterOperationsForFilter(
    CompositorFilterOperations& operations) const {
  auto filter = FilterOperationsIncludingReflection();
  FloatRect reference_box = FilterReferenceBox();
  if (!operations.IsEmpty() && !filter_on_effect_node_dirty_ &&
      reference_box == operations.ReferenceBox())
    return;
  float zoom = GetLayoutObject().StyleRef().EffectiveZoom();
  operations =
      FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter);
}

void PaintLayer::UpdateCompositorFilterOperationsForBackdropFilter(
    CompositorFilterOperations& operations,
    gfx::RRectF* backdrop_filter_bounds) const {
  DCHECK(backdrop_filter_bounds);
  const auto& style = GetLayoutObject().StyleRef();
  if (style.BackdropFilter().IsEmpty()) {
    operations.Clear();
    return;
  }
  FloatRect reference_box = BackdropFilterReferenceBox();
  *backdrop_filter_bounds = BackdropFilterBounds(reference_box);
  if (operations.IsEmpty() || reference_box != operations.ReferenceBox())
    operations = CreateCompositorFilterOperationsForBackdropFilter();
}

CompositorFilterOperations
PaintLayer::CreateCompositorFilterOperationsForBackdropFilter() const {
  const auto& style = GetLayoutObject().StyleRef();
  CompositorFilterOperations return_value;
  if (style.BackdropFilter().IsEmpty()) {
    return return_value;
  }
  float zoom = style.EffectiveZoom();
  FloatRect reference_box = BackdropFilterReferenceBox();
  return_value = FilterEffectBuilder(reference_box, zoom)
                     .BuildFilterOperations(style.BackdropFilter());
  DCHECK(!return_value.IsEmpty());
  return return_value;
}

PaintLayerResourceInfo& PaintLayer::EnsureResourceInfo() {
  PaintLayerRareData& rare_data = EnsureRareData();
  if (!rare_data.resource_info) {
    rare_data.resource_info =
        MakeGarbageCollected<PaintLayerResourceInfo>(this);
  }
  return *rare_data.resource_info;
}

void PaintLayer::RemoveAncestorOverflowLayer(const PaintLayer* removed_layer) {
  // If the current ancestor overflow layer does not match the removed layer
  // the ancestor overflow layer has changed so we can stop searching.
  if (AncestorOverflowLayer() && AncestorOverflowLayer() != removed_layer)
    return;

  if (AncestorOverflowLayer()) {
    // If the previous AncestorOverflowLayer is the root and this object is a
    // sticky viewport constrained object, it is no longer known to be
    // constrained by the root.
    if (AncestorOverflowLayer()->IsRootLayer() &&
        GetLayoutObject().StyleRef().HasStickyConstrainedPosition()) {
      if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
        frame_view->RemoveViewportConstrainedObject(GetLayoutObject());
    }

    if (PaintLayerScrollableArea* ancestor_scrollable_area =
            AncestorOverflowLayer()->GetScrollableArea()) {
      // TODO(pdr): When CompositeAfterPaint is enabled, we will need to
      // invalidate the scroll paint property subtree for this so main thread
      // scroll reasons are recomputed.
      ancestor_scrollable_area->InvalidateStickyConstraintsFor(this);
    }
  }
  UpdateAncestorOverflowLayer(nullptr);
  PaintLayer* current = first_;
  while (current) {
    current->RemoveAncestorOverflowLayer(removed_layer);
    current = current->NextSibling();
  }
}

FloatRect PaintLayer::MapRectForFilter(const FloatRect& rect) const {
  if (!HasFilterThatMovesPixels())
    return rect;
  return FilterOperationsIncludingReflection().MapRect(rect);
}

LayoutRect PaintLayer::MapLayoutRectForFilter(const LayoutRect& rect) const {
  if (!HasFilterThatMovesPixels())
    return rect;
  return EnclosingLayoutRect(MapRectForFilter(FloatRect(rect)));
}

bool PaintLayer::HasFilterThatMovesPixels() const {
  if (!HasFilterInducingProperty())
    return false;
  const ComputedStyle& style = GetLayoutObject().StyleRef();
  if (style.HasFilter() && style.Filter().HasFilterThatMovesPixels())
    return true;
  if (style.HasBoxReflect())
    return true;
  return false;
}

void PaintLayer::AddLayerHitTestRects(
    LayerHitTestRects& rects,
    TouchAction supported_fast_actions) const {
  ComputeSelfHitTestRects(rects, supported_fast_actions);
  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
    child->AddLayerHitTestRects(rects, supported_fast_actions);
}

void PaintLayer::ComputeSelfHitTestRects(
    LayerHitTestRects& rects,
    TouchAction supported_fast_actions) const {
  if (!Size().IsEmpty()) {
    Vector<HitTestRect> rect;
    TouchAction whitelisted_touch_action =
        GetLayoutObject().StyleRef().GetEffectiveTouchAction() &
        supported_fast_actions;

    if (GetLayoutBox() && GetLayoutBox()->ScrollsOverflow()) {
      // For scrolling layers, rects are taken to be in the space of the
      // contents.  We need to include the bounding box of the layer in the
      // space of its parent (eg. for border / scroll bars) and if it's
      // composited then the entire contents as well as they may be on another
      // composited layer. Skip reporting contents for non-composited layers as
      // they'll get projected to the same layer as the bounding box.
      if (GetCompositingState() != kNotComposited && scrollable_area_) {
        rect.push_back(HitTestRect(scrollable_area_->OverflowRect(),
                                   whitelisted_touch_action));
      }

      rects.Set(this, rect);
      if (const PaintLayer* parent_layer = Parent()) {
        LayerHitTestRects::iterator iter = rects.find(parent_layer);
        if (iter == rects.end()) {
          rects.insert(parent_layer, Vector<HitTestRect>())
              .stored_value->value.push_back(HitTestRect(
                  PhysicalBoundingBox(parent_layer), whitelisted_touch_action));
        } else {
          iter->value.push_back(HitTestRect(PhysicalBoundingBox(parent_layer),
                                            whitelisted_touch_action));
        }
      }
    } else {
      rect.push_back(
          HitTestRect(LogicalBoundingBox(), whitelisted_touch_action));
      rects.Set(this, rect);
    }
  }
}

void PaintLayer::SetNeedsRepaint() {
  SetNeedsRepaintInternal();

  // If you need repaint, then you might issue raster invalidations, and in
  // Composite after Paint mode, we do these in PAC::Update().
  LocalFrameView* frame_view = GetLayoutObject().GetDocument().View();
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && frame_view) {
    frame_view->SetPaintArtifactCompositorNeedsUpdate();
  }

  // Do this unconditionally to ensure container chain is marked when
  // compositing status of the layer changes.
  MarkCompositingContainerChainForNeedsRepaint();
}

void PaintLayer::SetNeedsRepaintInternal() {
  needs_repaint_ = true;
  // Invalidate as a display item client.
  static_cast<DisplayItemClient*>(this)->Invalidate();
}

void PaintLayer::MarkCompositingContainerChainForNeedsRepaint() {
  // Need to access compositingState(). We've ensured correct flag setting when
  // compositingState() changes.
  DisableCompositingQueryAsserts disabler;

  PaintLayer* layer = this;
  while (true) {
    if (layer->GetCompositingState() == kPaintsIntoOwnBacking)
      return;
    if (CompositedLayerMapping* grouped_mapping = layer->GroupedMapping()) {
      // TODO(wkorman): As we clean up the CompositedLayerMapping needsRepaint
      // logic to delegate to scrollbars, we may be able to remove the line
      // below as well.
      grouped_mapping->OwningLayer().SetNeedsRepaint();
      return;
    }

    // For a non-self-painting layer having self-painting descendant, the
    // descendant will be painted through this layer's Parent() instead of
    // this layer's Container(), so in addition to the CompositingContainer()
    // chain, we also need to mark NeedsRepaint for Parent().
    // TODO(crbug.com/828103): clean up this.
    if (layer->Parent() && !layer->IsSelfPaintingLayer())
      layer->Parent()->SetNeedsRepaint();

    PaintLayer* container = layer->CompositingContainer();
    if (!container) {
      auto* owner = layer->GetLayoutObject().GetFrame()->OwnerLayoutObject();
      if (!owner)
        break;
      container = owner->EnclosingLayer();
    }

    if (container->needs_repaint_)
      break;

    container->SetNeedsRepaintInternal();
    layer = container;
  }
}

void PaintLayer::ClearNeedsRepaintRecursively() {
  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
    child->ClearNeedsRepaintRecursively();
  needs_repaint_ = false;
}

DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
    : disabler_(&g_compositing_query_mode, kCompositingQueriesAreAllowed) {}

}  // namespace blink

#if DCHECK_IS_ON()
void showLayerTree(const blink::PaintLayer* layer) {
  blink::DisableCompositingQueryAsserts disabler;
  if (!layer) {
    LOG(ERROR) << "Cannot showLayerTree. Root is (nil)";
    return;
  }

  if (blink::LocalFrame* frame = layer->GetLayoutObject().GetFrame()) {
    WTF::String output =
        ExternalRepresentation(frame,
                               blink::kLayoutAsTextShowAllLayers |
                                   blink::kLayoutAsTextShowLayerNesting |
                                   blink::kLayoutAsTextShowCompositedLayers |
                                   blink::kLayoutAsTextShowAddresses |
                                   blink::kLayoutAsTextShowIDAndClass |
                                   blink::kLayoutAsTextDontUpdateLayout |
                                   blink::kLayoutAsTextShowLayoutState |
                                   blink::kLayoutAsTextShowPaintProperties,
                               layer);
    LOG(ERROR) << output.Utf8().data();
  }
}

void showLayerTree(const blink::LayoutObject* layoutObject) {
  if (!layoutObject) {
    LOG(ERROR) << "Cannot showLayerTree. Root is (nil)";
    return;
  }
  showLayerTree(layoutObject->EnclosingLayer());
}
#endif
