/*
 * 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/pseudo_style_request.h"
#include "third_party/blink/renderer/core/css_property_names.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/root_scroller_util.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/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/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/length_functions.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;

struct SameSizeAsPaintLayer : DisplayItemClient {
  int bit_fields;
#if DCHECK_IS_ON()
  int bit_fields2;
#endif
  void* pointers[11];
  LayoutUnit layout_units[4];
  IntSize size;
  Persistent<PaintLayerScrollableArea> scrollable_area;
  struct {
    IntSize size;
    LayoutRect rect;
  } previous_paint_status;
};

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

}  // namespace

using namespace HTMLNames;

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)
    : has_self_painting_layer_descendant_(false),
      has_self_painting_layer_descendant_dirty_(false),
      is_root_layer_(layout_object.IsLayoutView()),
      has_visible_content_(false),
      needs_descendant_dependent_flags_update_(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_(true),
      child_needs_compositing_inputs_update_(true),
      has_compositing_descendant_(false),
      is_all_scrolling_content_composited_(false),
      should_isolate_composited_descendants_(false),
      lost_grouped_mapping_(false),
      needs_repaint_(false),
      previous_paint_result_(kFullyPainted),
      needs_paint_phase_descendant_outlines_(false),
      previous_paint_phase_descendant_outlines_was_empty_(false),
      needs_paint_phase_float_(false),
      previous_paint_phase_float_was_empty_(false),
      needs_paint_phase_descendant_block_backgrounds_(false),
      previous_paint_phase_descendant_block_backgrounds_was_empty_(false),
      has_descendant_with_clip_path_(false),
      has_non_isolated_descendant_with_blend_mode_(false),
      has_descendant_with_sticky_or_fixed_(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_(true),
      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) {
  UpdateStackingNode();

  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();
}

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

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
  // LayoutTests/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;
}

bool PaintLayer::PaintsWithBackdropFilters() const {
  if (!GetLayoutObject().HasBackdropFilter())
    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) {
  switch (behavior) {
    case AllLayers:
      UpdateLayerPosition();
      break;
    case OnlyStickyLayers:
      if (GetLayoutObject().Style()->HasStickyConstrainedPosition())
        UpdateLayerPosition();
      if (PaintLayerScrollableArea* scroller = GetScrollableArea()) {
        if (!scroller->HasStickyDescendants())
          return;
      }
      break;
    default:
      NOTREACHED();
  }

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

void PaintLayer::UpdateHasSelfPaintingLayerDescendant() const {
  DCHECK(has_self_painting_layer_descendant_dirty_);

  has_self_painting_layer_descendant_ = false;

  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling()) {
    if (child->IsSelfPaintingLayer() ||
        child->HasSelfPaintingLayerDescendant()) {
      has_self_painting_layer_descendant_ = true;
      break;
    }
  }

  has_self_painting_layer_descendant_dirty_ = false;
}

void PaintLayer::DirtyAncestorChainHasSelfPaintingLayerDescendantStatus() {
  for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
    layer->has_self_painting_layer_descendant_dirty_ = true;
    // If we have reached a self-painting layer, we know our parent should have
    // a self-painting descendant in this case, there is no need to dirty our
    // ancestors further.
    if (layer->IsSelfPaintingLayer()) {
      DCHECK(!Parent() || Parent()->has_self_painting_layer_descendant_dirty_ ||
             Parent()->has_self_painting_layer_descendant_);
      break;
    }
  }
}

bool PaintLayer::SticksToScroller() const {
  if (GetLayoutObject().Style()->GetPosition() != EPosition::kSticky)
    return false;
  if (auto* ancestor_scrollable_area =
          AncestorOverflowLayer()->GetScrollableArea()) {
    return ancestor_scrollable_area->GetStickyConstraintsMap()
        .at(const_cast<PaintLayer*>(this))
        .GetAnchorEdges();
  }
  return false;
}

bool PaintLayer::FixedToViewport() const {
  if (GetLayoutObject().Style()->GetPosition() != EPosition::kFixed)
    return false;

  // TODO(pdr): This approach of calculating the nearest scroll node is O(n).
  // An option for improving this is to cache the nearest scroll node in
  // the local border box properties.
  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
    const auto view_border_box_properties =
        GetLayoutObject().View()->FirstFragment().LocalBorderBoxProperties();
    const auto* view_scroll = view_border_box_properties.Transform()
                                  ->NearestScrollTranslationNode()
                                  .ScrollNode();

    const auto* scroll = GetLayoutObject()
                             .FirstFragment()
                             .LocalBorderBoxProperties()
                             .Transform()
                             ->NearestScrollTranslationNode()
                             .ScrollNode();
    return scroll == view_scroll;
  }

  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);
    return;
  }
  ClearClipRects();
  UpdateLayerPositionRecursive(AllLayers);
}

void PaintLayer::UpdateTransformationMatrix() {
  if (TransformationMatrix* transform = Transform()) {
    LayoutBox* box = GetLayoutBox();
    DCHECK(box);
    transform->MakeIdentity();
    box->Style()->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;
  }

  // hasTransform() on the layoutObject 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();
    MarkAncestorChainForDescendantDependentFlagsUpdate();
  }

  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;

  LayoutBoxModelObject& transformed_ancestor =
      paint_invalidation_layer->TransformAncestorOrRoot().GetLayoutObject();

  // |paintInvalidationContainer| may have a local 2D transform on it, so take
  // that into account when mapping into the space of the transformed ancestor.
  point = paint_invalidation_container.LocalToAncestorPoint(
      point, &transformed_ancestor);
  // Don't include composited scroll offsets, since
  // SquashingOffsetFromTransformedAncestor does not.
  if (transformed_ancestor.UsesCompositedScrolling())
    point.Move(ToLayoutBox(transformed_ancestor).ScrolledContentOffset());

  point.MoveBy(-paint_invalidation_layer->GroupedMapping()
                    ->SquashingOffsetFromTransformedAncestor());
}

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

  LayoutBoxModelObject& transformed_ancestor =
      paint_invalidation_layer->TransformAncestorOrRoot().GetLayoutObject();

  // |paintInvalidationContainer| may have a local 2D transform on it, so take
  // that into account when mapping into the space of the transformed ancestor.
  rect = LayoutRect(
      paint_invalidation_container
          .LocalToAncestorQuad(FloatRect(rect), &transformed_ancestor)
          .BoundingBox());
  // Don't include composited scroll offsets, since
  // SquashingOffsetFromTransformedAncestor does not.
  if (transformed_ancestor.UsesCompositedScrolling())
    rect.Move(ToLayoutBox(transformed_ancestor).ScrolledContentOffset());

  rect.MoveBy(-paint_invalidation_layer->GroupedMapping()
                   ->SquashingOffsetFromTransformedAncestor());
}

void PaintLayer::MapRectToPaintInvalidationBacking(
    const LayoutObject& layout_object,
    const LayoutBoxModelObject& paint_invalidation_container,
    LayoutRect& rect) {
  if (!paint_invalidation_container.Layer()->GroupedMapping()) {
    layout_object.MapToVisualRectInAncestorSpace(&paint_invalidation_container,
                                                 rect);
    return;
  }

  // This code adjusts the visual rect to be in the space of the transformed
  // ancestor of the grouped (i.e. squashed) layer. This is because all layers
  // that squash together need to issue paint invalidations w.r.t. a single
  // container that is an ancestor of all of them, in order to properly take
  // into account any local transforms etc.
  // FIXME: remove this special-case code that works around the paint
  // invalidation code structure.
  layout_object.MapToVisualRectInAncestorSpace(&paint_invalidation_container,
                                               rect);

  MapRectInPaintInvalidationContainerToBacking(paint_invalidation_container,
                                               rect);
}

void PaintLayer::DirtyVisibleContentStatus() {
  MarkAncestorChainForDescendantDependentFlagsUpdate();
  // 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::MarkAncestorChainForDescendantDependentFlagsUpdate() {
  for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
    if (layer->needs_descendant_dependent_flags_update_)
      break;
    layer->needs_descendant_dependent_flags_update_ = true;
    layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
  }
}

// FIXME: this is quite brute-force. We could be more efficient if we were to
// track state and update it as appropriate as changes are made in the layout
// tree.
void PaintLayer::UpdateScrollingStateAfterCompositingChange() {
  TRACE_EVENT0("blink",
               "PaintLayer::updateScrollingStateAfterCompositingChange");
  is_all_scrolling_content_composited_ = true;
  for (LayoutObject* r = GetLayoutObject().SlowFirstChild(); r;
       r = r->NextSibling()) {
    if (!r->HasLayer()) {
      is_all_scrolling_content_composited_ = false;
      return;
    }
  }

  for (PaintLayer* child = FirstChild(); child; child = child->NextSibling()) {
    if (child->GetCompositingState() == kNotComposited) {
      is_all_scrolling_content_composited_ = false;
      return;
    } else if (!child->StackingNode()->IsStackingContext()) {
      // If the child is composited, but not a stacking context, it may paint
      // negative z-index descendants into an ancestor's GraphicsLayer.
      is_all_scrolling_content_composited_ = false;
      return;
    }
  }
}

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_descendant_with_sticky_or_fixed_ = false;
    has_non_contained_absolute_position_descendant_ = false;

    bool can_contain_abs =
        GetLayoutObject().CanContainAbsolutePositionObjects();

    for (PaintLayer* child = FirstChild(); child;
         child = child->NextSibling()) {
      child->UpdateDescendantDependentFlags();

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

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

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

      has_descendant_with_sticky_or_fixed_ |=
          child->HasDescendantWithStickyOrFixed() ||
          child->GetLayoutObject().Style()->GetPosition() ==
              EPosition::kSticky ||
          child->GetLayoutObject().Style()->GetPosition() == EPosition::kFixed;

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

    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;
  }

  bool previously_has_visible_content = has_visible_content_;
  if (GetLayoutObject().Style()->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->Style()->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 m_layoutObject 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 invalidateTreeIfNeeded walk.
    layout_object_.SetMayNeedPaintInvalidation();
  }

  Update3DTransformedDescendantStatus();
}

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

  stacking_node_->UpdateZOrderLists();

  // 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 (PaintLayerStackingNode* node = iterator.Next()) {
    const PaintLayer& child_layer = *node->Layer();
    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().Style()->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();
  }
  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 (!StackingNode()->IsStacked())
    return IsSelfPaintingLayer() ? Parent() : ContainingLayer();
  if (PaintLayerStackingNode* ancestor_stacking_node =
          StackingNode()->AncestorStackingContextNode())
    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 udpate. Reduce call sites after SPv2 launch allows
  /// removal of CompositingInputsUpdater.
  MarkAncestorChainForDescendantDependentFlagsUpdate();
}

void PaintLayer::SetNeedsCompositingInputsUpdateInternal() {
  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) {
  EnsureAncestorDependentCompositingInputs() = compositing_inputs;
  needs_ancestor_dependent_compositing_inputs_update_ = false;
}

void PaintLayer::ClearChildNeedsCompositingInputsUpdate() {
  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) {
  WTF::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();

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

  if (child->StackingNode()->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.
    child->StackingNode()->DirtyStackingContextZOrderLists();
  }

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

  MarkAncestorChainForDescendantDependentFlagsUpdate();
  DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();

  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();

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

    if (old_child->StackingNode()->IsStacked() || old_child->FirstChild()) {
      // Dirty the z-order list in which we are contained.  When called via the
      // reattachment process in removeOnlyThisLayer, the layer may already be
      // disconnected from the main layer tree, so we need to null-check the
      // |stackingContext| value.
      old_child->StackingNode()->DirtyStackingContextZOrderLists();
    }
  }

  if (GetLayoutObject().Style()->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());

  DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();

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

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

  return old_child;
}

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

void PaintLayer::RemoveOnlyThisLayerAfterStyleChange() {
  if (!parent_)
    return;

  // 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();

  bool did_set_paint_invalidation = false;
  if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
    // 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.
      DisablePaintInvalidationStateAsserts disabler;
      ObjectPaintInvalidator(GetLayoutObject())
          .InvalidatePaintIncludingNonCompositingDescendants();
      GetLayoutObject()
          .SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
      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::SlimmingPaintV2Enabled() &&
      !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(
              previous_paint_invalidation_container);
      // 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() {
  DCHECK(!stacking_node_);
  if (RequiresStackingNode())
    stacking_node_ = std::make_unique<PaintLayerStackingNode>(this);
  else
    stacking_node_ = nullptr;
}

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().Style()->Resize() != EResize::kNone);
}

void PaintLayer::AppendSingleFragmentIgnoringPagination(
    PaintLayerFragments& fragments,
    const PaintLayer* root_layer,
    const LayoutRect* dirty_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, kUncachedClipRects, overlay_scrollbar_clip_behavior,
      respect_overflow_clip, sub_pixel_accumulation);
  Clipper(kUseGeometryMapper)
      .CalculateRects(clip_rects_context, &GetLayoutObject().FirstFragment(),
                      dirty_rect, fragment.layer_bounds,
                      fragment.background_rect, fragment.foreground_rect,
                      offset_from_root);
  fragment.fragment_data = &GetLayoutObject().FirstFragment();
  fragments.push_back(fragment);
}

bool PaintLayer::ShouldFragmentCompositedBounds(
    const PaintLayer* compositing_layer) const {
  if (!EnclosingPaginationLayer())
    return false;
  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
    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 LayoutRect* dirty_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, kUncachedClipRects, overlay_scrollbar_clip_behavior,
      respect_overflow_clip, sub_pixel_accumulation);

  // The inherited offset_from_root does not include any pagination offsets.
  // In the presence of fragmentation, we cannot use it. Note that we may also
  // create fragments when ShouldFragmentCompositedBounds() is false, e.g. for
  // fixed-position objects in paged media.
  bool offset_from_root_can_be_used =
      offset_from_root && !ShouldFragmentCompositedBounds(root_layer) &&
      !GetLayoutObject().FirstFragment().NextFragment();
  for (auto* fragment_data = &GetLayoutObject().FirstFragment(); fragment_data;
       fragment_data = fragment_data->NextFragment()) {
    Clipper(kUseGeometryMapper)
        .CalculateRects(
            clip_rects_context, fragment_data, dirty_rect,
            fragment.layer_bounds, fragment.background_rect,
            fragment.foreground_rect,
            offset_from_root_can_be_used ? offset_from_root : nullptr);

    fragment.fragment_data = fragment_data;
    fragment.pagination_offset = fragment_data->PaginationOffset();

    fragments.push_back(fragment);
  }
}

static inline LayoutRect FrameVisibleRect(LayoutObject& layout_object) {
  LocalFrameView* frame_view = layout_object.GetDocument().View();
  if (!frame_view)
    return LayoutRect();

  return LayoutRect(LayoutPoint(), LayoutSize(frame_view->Size()));
}

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

bool PaintLayer::HitTest(HitTestResult& result) {
  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();
  const HitTestLocation& hit_test_location = result.GetHitTestLocation();

  // Start with frameVisibleRect to ensure we include the scrollbars.
  LayoutRect hit_test_area = FrameVisibleRect(GetLayoutObject());
  if (request.IgnoreClipping()) {
    if (LocalFrameView* frame_view = GetLayoutObject().GetDocument().View()) {
      hit_test_area.Unite(frame_view->DocumentToFrame(
          LayoutRect(GetLayoutObject().View()->DocumentRect())));
    }
  }

  HitTestRecursionData recursion_data(hit_test_area, 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();
}

scoped_refptr<HitTestingTransformState> PaintLayer::CreateLocalTransformState(
    PaintLayer* root_layer,
    PaintLayer* container_layer,
    const HitTestRecursionData& recursion_data,
    const HitTestingTransformState* container_transform_state,
    const LayoutPoint& translation_offset) const {
  scoped_refptr<HitTestingTransformState> transform_state;
  LayoutPoint offset;
  if (container_transform_state) {
    // If we're already computing transform state, then it's relative to the
    // container (which we know is non-null).
    transform_state =
        HitTestingTransformState::Create(*container_transform_state);
    ConvertToLayerCoords(container_layer, offset);
  } else {
    // If this is the first time we need to make transform state, then base it
    // off of hitTestLocation, which is relative to rootLayer.
    transform_state = HitTestingTransformState::Create(
        recursion_data.location.TransformedPoint(),
        recursion_data.location.TransformedRect(),
        FloatQuad(FloatRect(recursion_data.rect)));
    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,
    const HitTestingTransformState* transform_state,
    double* z_offset) {
  const LayoutObject& layout_object = GetLayoutObject();
  DCHECK_GE(layout_object.GetDocument().Lifecycle().GetState(),
            DocumentLifecycle::kCompositingClean);

  if (!IsSelfPaintingLayer() && !HasSelfPaintingLayerDescendant())
    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(PaintLayer::kUseGeometryMapper)
          .CalculateBackgroundClipRect(
              ClipRectsContext(root_layer, 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.
  scoped_refptr<HitTestingTransformState> local_transform_state;
  if (applied_transform) {
    // We computed the correct state in the caller (above code), so just
    // reference it.
    DCHECK(transform_state);
    local_transform_state =
        const_cast<HitTestingTransformState*>(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.
    local_transform_state = CreateLocalTransformState(
        root_layer, container_layer, recursion_data, transform_state);
  }

  // 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;
  }

  scoped_refptr<HitTestingTransformState> unflattened_transform_state =
      local_transform_state;
  if (local_transform_state && !Preserves3D()) {
    // Keep a copy of the pre-flattening state, for computing z-offsets for the
    // container
    unflattened_transform_state =
        HitTestingTransformState::Create(*local_transform_state);
    // 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.get(), z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state.get(), 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.get(), z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state.get(), 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(),
                                result.GetHitTestLocation());
      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.get())) {
        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.get(), z_offset_for_descendants_ptr, z_offset,
      unflattened_transform_state.get(), 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(),
                              result.GetHitTestLocation());
    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.get())) {
      if (result.IsRectBasedTest())
        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,
    const 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.pagination_offset);
    if (hit_layer)
      return hit_layer;
  }

  return nullptr;
}

PaintLayer* PaintLayer::HitTestLayerByApplyingTransform(
    PaintLayer* root_layer,
    PaintLayer* container_layer,
    HitTestResult& result,
    const HitTestRecursionData& recursion_data,
    const HitTestingTransformState* transform_state,
    double* z_offset,
    const LayoutPoint& translation_offset) {
  // Create a transform state to accumulate this transform.
  scoped_refptr<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);

  // 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.get(), 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 rect-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() {
  if (!GetLayoutObject().IsSVGForeignObject())
    return false;
  if (!GetLayoutObject().StyleRef().HasAutoZIndex())
    return false;
  return true;
}

PaintLayer* PaintLayer::HitTestChildren(
    ChildrenIteration childrento_visit,
    PaintLayer* root_layer,
    HitTestResult& result,
    const HitTestRecursionData& recursion_data,
    const HitTestingTransformState* transform_state,
    double* z_offset_for_descendants,
    double* z_offset,
    const HitTestingTransformState* unflattened_transform_state,
    bool depth_sort_descendants) {
  if (!HasSelfPaintingLayerDescendant())
    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 (PaintLayerStackingNode* child = iterator.Next()) {
    PaintLayer* child_layer = child->Layer();

    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(),
                              result.GetHitTestLocation());
    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.
    DCHECK(!result.IsRectBasedTest() || result.GetHitTestRequest().ListBased());
    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;
}

FloatRect PaintLayer::FilterReferenceBox(const FilterOperations& filter,
                                         float zoom) const {
  if (!filter.HasReferenceFilter())
    return FloatRect();

  FloatRect reference_box(PhysicalBoundingBoxIncludingStackingChildren(
      LayoutPoint(), PaintLayer::CalculateBoundsOptions::
                         kIncludeTransformsAndCompositedChildLayers));
  if (zoom != 1)
    reference_box.Scale(1 / zoom);
  return reference_box;
}

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

  LayoutRect reference_box(
      ClipPathClipper::LocalReferenceBox(GetLayoutObject()));
  if (EnclosingPaginationLayer())
    ConvertFromFlowThreadToVisualBoundingBoxInAncestor(root_layer,
                                                       reference_box);
  else
    ConvertToLayerCoords(root_layer, reference_box);

  FloatPoint point(hit_test_location.Point());
  FloatRect float_reference_box(reference_box);

  ClipPathOperation* clip_path_operation =
      GetLayoutObject().Style()->ClipPath();
  DCHECK(clip_path_operation);
  if (clip_path_operation->GetType() == ClipPathOperation::SHAPE) {
    ShapeClipPathOperation* clip_path =
        ToShapeClipPathOperation(clip_path_operation);
    return !clip_path->GetPath(float_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);
  float_reference_box.Scale(inverse_zoom);
  return !clipper->HitTestClipContent(float_reference_box, point);
}

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 (RootScrollerUtil::IsEffective(*this) || 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 {
  DCHECK(StackingNode()->IsStackingContext() ||
         !StackingNode()->HasPositiveZOrderList());

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

  PaintLayerStackingNodeIterator iterator(*StackingNode(), kAllChildren);
  while (PaintLayerStackingNode* node = 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 &&
        node->Layer()->GetCompositingState() != kNotComposited)
      continue;
    result.Unite(node->Layer()->BoundingBoxForCompositingInternal(
        composited_layer, this, options));
  }
}

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

  const_cast<PaintLayer*>(this)->StackingNode()->UpdateLayerListsIfNeeded();

  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 (RootScrollerUtil::IsEffective(*this) || 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();

  const_cast<PaintLayer*>(this)->StackingNode()->UpdateLayerListsIfNeeded();

  // If there is a clip applied by an ancestor to this PaintLayer but below or
  // equal to |ancestorLayer|, apply that clip.
  LayoutRect result = Clipper(PaintLayer::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::SlimmingPaintV2Enabled())
    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();
  }
}

BackgroundPaintLocation PaintLayer::GetBackgroundPaintLocation(
    uint32_t* reasons) const {
  BackgroundPaintLocation location;
  bool may_have_scrolling_layers_without_scrolling = IsRootLayer();
  if (!ScrollsOverflow() && !may_have_scrolling_layers_without_scrolling) {
    location = kBackgroundPaintInGraphicsLayer;
  } else {
    // If we care about LCD text, paint root backgrounds into scrolling contents
    // layer even if style suggests otherwise. (For non-root scrollers, we just
    // avoid compositing - see PLSA::ComputeNeedsCompositedScrolling.)
    DCHECK(Compositor());
    if (IsRootLayer() && !Compositor()->PreferCompositingToLCDTextEnabled())
      location = kBackgroundPaintInScrollingContents;
    else
      location = GetLayoutObject().GetBackgroundPaintLocation(reasons);
  }
  if (!IsRootLayer()) {
    stacking_node_->UpdateLayerListsIfNeeded();
    if (stacking_node_->HasNegativeZOrderList())
      location = kBackgroundPaintInGraphicsLayer;
  }
  return location;
}

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);

  if (PaintLayerResourceInfo* resource_info = ResourceInfo())
    resource_info->InvalidateFilterChain();
}

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();

  if (layer_being_destroyed)
    return;

  if (PaintLayerResourceInfo* resource_info = ResourceInfo())
    resource_info->InvalidateFilterChain();
}

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::MaskBlendingAppliedByCompositor(
    const PaintInfo& paint_info) const {
  DCHECK(layout_object_.HasMask());
  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
    return true;

  if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
    return false;

  return rare_data_ && rare_data_->composited_layer_mapping &&
         rare_data_->composited_layer_mapping->HasMaskLayer();
}

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 documents paint atomically.
  if (GetLayoutObject().IsSVGRoot() &&
      GetLayoutObject().GetDocument().IsSVGDocument())
    return true;

  // Create subsequence for only stacking contexts whose painting are atomic.
  return StackingNode()->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().Style()->HasOpacity();
}

bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
    const LayoutRect& local_rect) 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().Style()->Visibility() != EVisibility::kVisible)
    return false;

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

  if (PaintsWithFilters() &&
      GetLayoutObject().Style()->Filter().HasFilterThatAffectsOpacity())
    return false;

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

  if (!RuntimeEnabledFeatures::CompositeOpaqueFixedPositionEnabled() &&
      GetLayoutObject().Style()->GetPosition() == EPosition::kFixed &&
      GetCompositingState() != kPaintsIntoOwnBacking)
    return false;

  // This function should not be called when layer-lists are dirty.
  // TODO(schenney) This check never hits in layout tests or most platforms, but
  // does hit in PopupBlockerBrowserTest.AllowPopupThroughContentSetting on
  // Win 7 Test Builder.
  if (stacking_node_->ZOrderListsDirty())
    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;

  // 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 {
  PaintLayerStackingNodeReverseIterator reverse_iterator(
      *stacking_node_,
      kPositiveZOrderChildren | kNormalFlowChildren | kNegativeZOrderChildren);
  while (PaintLayerStackingNode* child = reverse_iterator.Next()) {
    const PaintLayer* child_layer = child->Layer();
    // 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))
      return true;
  }
  return false;
}

bool PaintLayer::ShouldBeSelfPaintingLayer() const {
  if (GetLayoutObject().IsLayoutEmbeddedContent() &&
      ToLayoutEmbeddedContent(GetLayoutObject())
          .RequiresAcceleratedCompositing())
    return true;

  // 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;
  SetNeedsRepaint();

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

    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().Style()->HasBoxDecorations() ||
         GetLayoutObject().Style()->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());
  if (PaintLayerResourceInfo* resource_info = ResourceInfo())
    resource_info->InvalidateFilterChain();
}

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;

  // To cut off almost all the work in the compositing update for
  // this case, we treat inline transforms has having assumed overlap
  // (similar to how we treat animated transforms). Notice that we read
  // CompositingReasonInlineTransform from the m_compositingReasons, which
  // means that the inline transform actually triggered assumed overlap in
  // the overlap map.
  if (diff.TransformChanged() &&
      (!rare_data_ || !(rare_data_->compositing_reasons &
                        CompositingReason::kInlineTransform)))
    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_.Style()->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_.Style()->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))
    return;

  stacking_node_->StyleDidChange(old_style);

  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();

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

  SetNeedsCompositingInputsUpdate();
  GetLayoutObject().SetNeedsPaintPropertyUpdate();

  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && !NeedsRepaint()) {
    if (diff.ZIndexChanged()) {
      // We don't need to invalidate paint of objects on SPv175 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) {
      // Change of PaintedOutputInvisible() will affect existence of paint
      // chunks, so needs repaint.
      PaintLayerPainter painter(*this);
      // It's fine for PaintedOutputInvisible() to access the current
      // compositing state.
      DisableCompositingQueryAsserts disable;
      if (painter.PaintedOutputInvisible(*old_style) !=
          painter.PaintedOutputInvisible(GetLayoutObject().StyleRef()))
        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 == 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 {
  const auto& style = GetLayoutObject().StyleRef();
  float zoom = style.EffectiveZoom();
  auto filter = FilterOperationsIncludingReflection();
  FloatRect reference_box = FilterReferenceBox(filter, zoom);
  if (!operations.IsEmpty() && !filter_on_effect_node_dirty_ &&
      reference_box == operations.ReferenceBox())
    return;

  operations =
      FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter);
}

CompositorFilterOperations
PaintLayer::CreateCompositorFilterOperationsForBackdropFilter() const {
  const auto& style = GetLayoutObject().StyleRef();
  float zoom = style.EffectiveZoom();
  FloatRect reference_box = FilterReferenceBox(style.BackdropFilter(), zoom);
  return FilterEffectBuilder(reference_box, zoom)
      .BuildFilterOperations(style.BackdropFilter());
}

PaintLayerResourceInfo& PaintLayer::EnsureResourceInfo() {
  PaintLayerRareData& rare_data = EnsureRareData();
  if (!rare_data.resource_info)
    rare_data.resource_info = new 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().Style()->HasStickyConstrainedPosition()) {
      if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
        frame_view->RemoveViewportConstrainedObject(GetLayoutObject());
    }

    if (PaintLayerScrollableArea* ancestor_scrollable_area =
            AncestorOverflowLayer()->GetScrollableArea()) {
      // TODO(pdr): When slimming paint v2 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();
  }
}

FilterEffect* PaintLayer::LastFilterEffect() const {
  // TODO(chrishtr): ensure (and assert) that compositing is clean here.
  if (!PaintsWithFilters())
    return nullptr;
  PaintLayerResourceInfo* resource_info = ResourceInfo();
  DCHECK(resource_info);

  if (resource_info->LastEffect())
    return resource_info->LastEffect();

  const auto& style = GetLayoutObject().StyleRef();
  float zoom = style.EffectiveZoom();
  FilterEffectBuilder builder(FilterReferenceBox(style.Filter(), zoom), zoom);
  resource_info->SetLastEffect(
      builder.BuildFilterEffect(FilterOperationsIncludingReflection()));
  return resource_info->LastEffect();
}

FloatRect PaintLayer::MapRectForFilter(const FloatRect& rect) const {
  if (!HasFilterThatMovesPixels())
    return rect;

  // Ensure the filter-chain is refreshed wrt reference filters.
  // TODO(fs): Avoid having this side-effect inducing call.
  LastFilterEffect();

  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<TouchActionRect> rect;
    TouchAction whitelisted_touch_action =
        GetLayoutObject().Style()->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(TouchActionRect(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<TouchActionRect>())
              .stored_value->value.push_back(TouchActionRect(
                  PhysicalBoundingBox(parent_layer), whitelisted_touch_action));
        } else {
          iter->value.push_back(TouchActionRect(
              PhysicalBoundingBox(parent_layer), whitelisted_touch_action));
        }
      }
    } else {
      rect.push_back(
          TouchActionRect(LogicalBoundingBox(), whitelisted_touch_action));
      rects.Set(this, rect);
    }
  }
}

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

  // 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.
  SetDisplayItemsUncached();
}

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
