// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/paint/PaintPropertyTreeBuilder.h"

#include <memory>
#include "core/dom/DOMNodeIds.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/Settings.h"
#include "core/layout/FragmentainerIterator.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutView.h"
#include "core/layout/svg/LayoutSVGResourceMasker.h"
#include "core/layout/svg/LayoutSVGRoot.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/paint/FindPaintOffsetAndVisualRectNeedingUpdate.h"
#include "core/paint/FindPropertiesNeedingUpdate.h"
#include "core/paint/ObjectPaintProperties.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/SVGRootPainter.h"
#include "core/paint/compositing/CompositedLayerMapping.h"
#include "core/paint/compositing/CompositingReasonFinder.h"
#include "platform/geometry/TransformState.h"
#include "platform/transforms/TransformationMatrix.h"
#include "platform/wtf/PtrUtil.h"

namespace blink {

PaintPropertyTreeBuilderFragmentContext::
    PaintPropertyTreeBuilderFragmentContext()
    : current_effect(EffectPaintPropertyNode::Root()) {
  current.clip = absolute_position.clip = fixed_position.clip =
      ClipPaintPropertyNode::Root();
  current.transform = absolute_position.transform = fixed_position.transform =
      TransformPaintPropertyNode::Root();
  current.scroll = absolute_position.scroll = fixed_position.scroll =
      ScrollPaintPropertyNode::Root();
}

// True if a new property was created, false if an existing one was updated.
static bool UpdatePreTranslation(
    LocalFrameView& frame_view,
    scoped_refptr<const TransformPaintPropertyNode> parent,
    const TransformationMatrix& matrix,
    const FloatPoint3D& origin) {
  DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
  if (auto* existing_pre_translation = frame_view.PreTranslation()) {
    existing_pre_translation->Update(std::move(parent), matrix, origin);
    return false;
  }
  frame_view.SetPreTranslation(
      TransformPaintPropertyNode::Create(std::move(parent), matrix, origin));
  return true;
}

// True if a new property was created, false if an existing one was updated.
static bool UpdateContentClip(
    LocalFrameView& frame_view,
    scoped_refptr<const ClipPaintPropertyNode> parent,
    scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
    const FloatRoundedRect& clip_rect,
    bool& clip_changed) {
  DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
  if (auto* existing_content_clip = frame_view.ContentClip()) {
    if (existing_content_clip->ClipRect() != clip_rect)
      clip_changed = true;
    existing_content_clip->Update(std::move(parent),
                                  std::move(local_transform_space), clip_rect);
    return false;
  }
  frame_view.SetContentClip(ClipPaintPropertyNode::Create(
      std::move(parent), std::move(local_transform_space), clip_rect));
  clip_changed = true;
  return true;
}

static MainThreadScrollingReasons GetMainThreadScrollingReasons(
    const LocalFrameView& frame_view,
    MainThreadScrollingReasons ancestor_reasons) {
  auto reasons = ancestor_reasons;
  if (!frame_view.GetFrame().GetSettings()->GetThreadedScrollingEnabled())
    reasons |= MainThreadScrollingReason::kThreadedScrollingDisabled;
  if (frame_view.HasBackgroundAttachmentFixedObjects())
    reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
  return reasons;
}

// True if a new property was created or a main thread scrolling reason changed
// (which can affect descendants), false if an existing one was updated.
static bool UpdateScroll(LocalFrameView& frame_view,
                         PaintPropertyTreeBuilderFragmentContext& context) {
  DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
  IntRect container_rect(IntPoint(), frame_view.VisibleContentSize());
  IntRect contents_rect(-frame_view.ScrollOrigin(), frame_view.ContentsSize());
  bool user_scrollable_horizontal =
      frame_view.UserInputScrollable(kHorizontalScrollbar);
  bool user_scrollable_vertical =
      frame_view.UserInputScrollable(kVerticalScrollbar);
  auto ancestor_reasons =
      context.current.scroll->GetMainThreadScrollingReasons();
  auto main_thread_scrolling_reasons =
      GetMainThreadScrollingReasons(frame_view, ancestor_reasons);
  auto element_id = frame_view.GetCompositorElementId();

  if (auto* existing_scroll = frame_view.ScrollNode()) {
    auto existing_reasons = existing_scroll->GetMainThreadScrollingReasons();
    existing_scroll->Update(context.current.scroll, container_rect,
                            contents_rect, user_scrollable_horizontal,
                            user_scrollable_vertical,
                            main_thread_scrolling_reasons, element_id);
    return existing_reasons != main_thread_scrolling_reasons;
  }
  frame_view.SetScrollNode(ScrollPaintPropertyNode::Create(
      context.current.scroll, container_rect, contents_rect,
      user_scrollable_horizontal, user_scrollable_vertical,
      main_thread_scrolling_reasons, element_id));
  return true;
}

// True if a new property was created, false if an existing one was updated.
static bool UpdateScrollTranslation(
    LocalFrameView& frame_view,
    scoped_refptr<const TransformPaintPropertyNode> parent,
    const TransformationMatrix& matrix,
    scoped_refptr<ScrollPaintPropertyNode> scroll) {
  DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled());
  // TODO(pdr): Set the correct compositing reasons here.
  if (auto* existing_scroll_translation = frame_view.ScrollTranslation()) {
    existing_scroll_translation->Update(
        std::move(parent), matrix, FloatPoint3D(), false, 0,
        kCompositingReasonNone, CompositorElementId(), std::move(scroll));
    return false;
  }
  frame_view.SetScrollTranslation(TransformPaintPropertyNode::Create(
      std::move(parent), matrix, FloatPoint3D(), false, 0,
      kCompositingReasonNone, CompositorElementId(), std::move(scroll)));
  return true;
}

void FrameViewPaintPropertyTreeBuilder::Update(
    LocalFrameView& frame_view,
    PaintPropertyTreeBuilderContext& full_context) {
  if (full_context.fragments.IsEmpty())
    full_context.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());

  PaintPropertyTreeBuilderFragmentContext& context = full_context.fragments[0];
  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
    // With root layer scrolling, the LayoutView (a LayoutObject) properties are
    // updated like other objects (see updatePropertiesAndContextForSelf and
    // updatePropertiesAndContextForChildren) instead of needing LayoutView-
    // specific property updates here.
    context.current.paint_offset.MoveBy(frame_view.Location());
    context.current.rendering_context_id = 0;
    context.current.should_flatten_inherited_transform = true;
    context.absolute_position = context.current;
    full_context.container_for_absolute_position = nullptr;
    context.fixed_position = context.current;
    context.fixed_position.fixed_position_children_fixed_to_root = true;
    return;
  } else {
    context.current.paint_offset_root = frame_view.GetLayoutView();
  }

#if DCHECK_IS_ON()
  FindFrameViewPropertiesNeedingUpdateScope check_scope(
      &frame_view, full_context.is_actually_needed);
#endif

  if (frame_view.NeedsPaintPropertyUpdate() ||
      full_context.force_subtree_update) {
    TransformationMatrix frame_translate;
    frame_translate.Translate(
        frame_view.X() + context.current.paint_offset.X(),
        frame_view.Y() + context.current.paint_offset.Y());
    full_context.force_subtree_update |= UpdatePreTranslation(
        frame_view, context.current.transform, frame_translate, FloatPoint3D());

    FloatRoundedRect content_clip(
        IntRect(IntPoint(), frame_view.VisibleContentSize()));
    full_context.force_subtree_update |= UpdateContentClip(
        frame_view, context.current.clip, frame_view.PreTranslation(),
        content_clip, full_context.clip_changed);

    if (frame_view.IsScrollable()) {
      full_context.force_subtree_update |= UpdateScroll(frame_view, context);
    } else if (frame_view.ScrollNode()) {
      // Ensure pre-existing properties are cleared if there is no scrolling.
      frame_view.SetScrollNode(nullptr);
      // Rebuild all descendant properties because a property was removed.
      full_context.force_subtree_update = true;
    }

    // A scroll translation node is created for static offset (e.g., overflow
    // hidden with scroll offset) or cases that scroll and have a scroll node.
    ScrollOffset scroll_offset = frame_view.GetScrollOffset();
    if (frame_view.IsScrollable() || !scroll_offset.IsZero()) {
      TransformationMatrix frame_scroll;
      frame_scroll.Translate(-scroll_offset.Width(), -scroll_offset.Height());
      full_context.force_subtree_update |=
          UpdateScrollTranslation(frame_view, frame_view.PreTranslation(),
                                  frame_scroll, frame_view.ScrollNode());
    } else if (frame_view.ScrollTranslation()) {
      // Ensure pre-existing properties are cleared if there is no scrolling.
      frame_view.SetScrollTranslation(nullptr);
      // Rebuild all descendant properties because a property was removed.
      full_context.force_subtree_update = true;
    }
    full_context.painting_layer = frame_view.GetLayoutView()->Layer();
  }

  // Initialize the context for current, absolute and fixed position cases.
  // They are the same, except that scroll translation does not apply to
  // fixed position descendants.
  const auto* fixed_transform_node = frame_view.PreTranslation()
                                         ? frame_view.PreTranslation()
                                         : context.current.transform;
  auto* fixed_scroll_node = context.current.scroll;
  DCHECK(frame_view.PreTranslation());
  context.current.transform = frame_view.PreTranslation();
  DCHECK(frame_view.ContentClip());
  context.current.clip = frame_view.ContentClip();
  if (const auto* scroll_node = frame_view.ScrollNode())
    context.current.scroll = scroll_node;
  if (const auto* scroll_translation = frame_view.ScrollTranslation())
    context.current.transform = scroll_translation;
  context.current.paint_offset = LayoutPoint();
  context.current.rendering_context_id = 0;
  context.current.should_flatten_inherited_transform = true;
  context.absolute_position = context.current;
  full_context.container_for_absolute_position = nullptr;
  context.fixed_position = context.current;
  context.fixed_position.transform = fixed_transform_node;
  context.fixed_position.scroll = fixed_scroll_node;
  context.fixed_position.fixed_position_children_fixed_to_root = true;

  std::unique_ptr<PropertyTreeState> contents_state(new PropertyTreeState(
      context.current.transform, context.current.clip, context.current_effect));
  frame_view.SetTotalPropertyTreeStateForContents(std::move(contents_state));
}

namespace {

class FragmentPaintPropertyTreeBuilder {
 public:
  FragmentPaintPropertyTreeBuilder(
      const LayoutObject& object,
      PaintPropertyTreeBuilderContext& full_context,
      PaintPropertyTreeBuilderFragmentContext& context,
      FragmentData& fragment_data)
      : object_(object),
        full_context_(full_context),
        context_(context),
        fragment_data_(fragment_data),
        properties_(fragment_data.GetRarePaintData()
                        ? fragment_data.GetRarePaintData()->PaintProperties()
                        : nullptr) {}

  ALWAYS_INLINE void UpdateForSelf();
  ALWAYS_INLINE void UpdateForChildren();

 private:
  ALWAYS_INLINE void UpdatePaintOffset();
  ALWAYS_INLINE void UpdateForPaintOffsetTranslation(Optional<IntPoint>&);
  ALWAYS_INLINE void UpdatePaintOffsetTranslation(const Optional<IntPoint>&);
  ALWAYS_INLINE void UpdateForObjectLocationAndSize(
      Optional<IntPoint>& paint_offset_translation);
  ALWAYS_INLINE void UpdateTransform();
  ALWAYS_INLINE void UpdateTransformForNonRootSVG();
  ALWAYS_INLINE void UpdateEffect();
  ALWAYS_INLINE void UpdateFilter();
  ALWAYS_INLINE void UpdateFragmentClip(const PaintLayer&);
  ALWAYS_INLINE void UpdateCssClip();
  ALWAYS_INLINE void UpdateLocalBorderBoxContext();
  ALWAYS_INLINE void UpdateOverflowClip();
  ALWAYS_INLINE void UpdatePerspective();
  ALWAYS_INLINE void UpdateSvgLocalToBorderBoxTransform();
  ALWAYS_INLINE void UpdateScrollAndScrollTranslation();
  ALWAYS_INLINE void UpdateOutOfFlowContext();

  const LayoutObject& object_;
  // The tree builder context for the whole object.
  PaintPropertyTreeBuilderContext& full_context_;
  // The tree builder context for the current fragment, which is one of the
  // entries in |full_context.fragments|.
  PaintPropertyTreeBuilderFragmentContext& context_;
  FragmentData& fragment_data_;
  ObjectPaintProperties* properties_;
};

static bool NeedsScrollNode(const LayoutObject& object) {
  if (!object.HasOverflowClip())
    return false;
  return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow();
}

// True if a scroll translation is needed for static scroll offset (e.g.,
// overflow hidden with scroll), or if a scroll node is needed for composited
// scrolling.
static bool NeedsScrollOrScrollTranslation(const LayoutObject& object) {
  if (!object.HasOverflowClip())
    return false;
  IntSize scroll_offset = ToLayoutBox(object).ScrolledContentOffset();
  return !scroll_offset.IsZero() || NeedsScrollNode(object);
}

static bool NeedsSVGLocalToBorderBoxTransform(const LayoutObject& object) {
  return object.IsSVGRoot();
}

static bool NeedsPaintOffsetTranslationForScrollbars(
    const LayoutBoxModelObject& object) {
  if (auto* area = object.GetScrollableArea()) {
    if (area->HorizontalScrollbar() || area->VerticalScrollbar())
      return true;
  }
  return false;
}

static bool NeedsPaintOffsetTranslation(const LayoutObject& object) {
  if (!object.IsBoxModelObject())
    return false;
  const LayoutBoxModelObject& box_model = ToLayoutBoxModelObject(object);
  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
      box_model.IsLayoutView()) {
    // Root layer scrolling always creates a translation node for LayoutView to
    // ensure fixed and absolute contexts use the correct transform space.
    return true;
  }
  if (box_model.HasLayer() && box_model.Layer()->PaintsWithTransform(
                                  kGlobalPaintFlattenCompositingLayers)) {
    return true;
  }
  if (NeedsScrollOrScrollTranslation(object))
    return true;
  if (NeedsPaintOffsetTranslationForScrollbars(box_model))
    return true;
  if (NeedsSVGLocalToBorderBoxTransform(object))
    return true;

  // Don't let paint offset cross composited layer boundaries, to avoid
  // unnecessary full layer paint/raster invalidation when paint offset in
  // ancestor transform node changes which should not affect the descendants
  // of the composited layer.
  // TODO(wangxianzhu): For SPv2, we also need a avoid unnecessary paint/raster
  // invalidation in composited layers when their paint offset changes.
  if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
      // For only LayoutBlocks that won't be escaped by floating objects and
      // column spans when finding their containing blocks.
      // TODO(crbug.com/780242): This can be avoided if we have fully correct
      // paint property tree states for floating objects and column spans.
      object.IsLayoutBlock() && object.HasLayer() &&
      !ToLayoutBoxModelObject(object).Layer()->EnclosingPaginationLayer() &&
      object.GetCompositingState() == kPaintsIntoOwnBacking)
    return true;

  return false;
}

IntPoint ApplyPaintOffsetTranslation(const LayoutObject& object,
                                     LayoutPoint& paint_offset) {
  // We should use the same subpixel paint offset values for snapping
  // regardless of whether a transform is present. If there is a transform
  // we round the paint offset but keep around the residual fractional
  // component for the transformed content to paint with.  In spv1 this was
  // called "subpixel accumulation". For more information, see
  // PaintLayer::subpixelAccumulation() and
  // PaintLayerPainter::paintFragmentByApplyingTransform.
  IntPoint paint_offset_translation = RoundedIntPoint(paint_offset);
  LayoutPoint fractional_paint_offset =
      LayoutPoint(paint_offset - paint_offset_translation);
  if (fractional_paint_offset != LayoutPoint()) {
    // If the object has a non-translation transform, discard the fractional
    // paint offset which can't be transformed by the transform.
    TransformationMatrix matrix;
    object.StyleRef().ApplyTransform(
        matrix, LayoutSize(), ComputedStyle::kExcludeTransformOrigin,
        ComputedStyle::kIncludeMotionPath,
        ComputedStyle::kIncludeIndependentTransformProperties);
    if (!matrix.IsIdentityOrTranslation())
      fractional_paint_offset = LayoutPoint();
  }
  paint_offset = fractional_paint_offset;
  return paint_offset_translation;
}

void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
    Optional<IntPoint>& paint_offset_translation) {
  if (!NeedsPaintOffsetTranslation(object_))
    return;

  paint_offset_translation =
      ApplyPaintOffsetTranslation(object_, context_.current.paint_offset);
  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
      object_.IsLayoutView()) {
    context_.absolute_position.paint_offset = context_.current.paint_offset;
    context_.fixed_position.paint_offset = context_.current.paint_offset;
  }
}

void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
    const Optional<IntPoint>& paint_offset_translation) {
  DCHECK(properties_);

  if (paint_offset_translation) {
    auto result = properties_->UpdatePaintOffsetTranslation(
        context_.current.transform,
        TransformationMatrix().Translate(paint_offset_translation->X(),
                                         paint_offset_translation->Y()),
        FloatPoint3D(), context_.current.should_flatten_inherited_transform,
        context_.current.rendering_context_id);
    context_.current.transform = properties_->PaintOffsetTranslation();
    if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
        object_.IsLayoutView()) {
      context_.absolute_position.transform =
          properties_->PaintOffsetTranslation();
      context_.fixed_position.transform = properties_->PaintOffsetTranslation();
    }

    full_context_.force_subtree_update |= result.NewNodeCreated();
  } else {
    full_context_.force_subtree_update |=
        properties_->ClearPaintOffsetTranslation();
  }
}

static bool NeedsTransformForNonRootSVG(const LayoutObject& object) {
  // TODO(pdr): Check for the presence of a transform instead of the value.
  // Checking for an identity matrix will cause the property tree structure
  // to change during animations if the animation passes through the
  // identity matrix.
  return object.IsSVGChild() &&
         !object.LocalToSVGParentTransform().IsIdentity();
}

// SVG does not use the general transform update of |UpdateTransform|, instead
// creating a transform node for SVG-specific transforms without 3D.
void FragmentPaintPropertyTreeBuilder::UpdateTransformForNonRootSVG() {
  DCHECK(properties_);
  DCHECK(object_.IsSVGChild());
  // SVG does not use paint offset internally, except for SVGForeignObject which
  // has different SVG and HTML coordinate spaces.
  DCHECK(object_.IsSVGForeignObject() ||
         context_.current.paint_offset == LayoutPoint());

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    AffineTransform transform = object_.LocalToSVGParentTransform();
    if (NeedsTransformForNonRootSVG(object_)) {
      // The origin is included in the local transform, so leave origin empty.
      auto result = properties_->UpdateTransform(
          context_.current.transform, TransformationMatrix(transform),
          FloatPoint3D());
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      full_context_.force_subtree_update |= properties_->ClearTransform();
    }
  }

  if (properties_->Transform()) {
    context_.current.transform = properties_->Transform();
    context_.current.should_flatten_inherited_transform = false;
    context_.current.rendering_context_id = 0;
  }
}

static CompositingReasons CompositingReasonsForTransform(const LayoutBox& box) {
  const ComputedStyle& style = box.StyleRef();
  CompositingReasons compositing_reasons = kCompositingReasonNone;
  if (CompositingReasonFinder::RequiresCompositingForTransform(box))
    compositing_reasons |= kCompositingReason3DTransform;

  if (CompositingReasonFinder::RequiresCompositingForTransformAnimation(style))
    compositing_reasons |= kCompositingReasonActiveAnimation;

  if (style.HasWillChangeCompositingHint() &&
      !style.SubtreeWillChangeContents())
    compositing_reasons |= kCompositingReasonWillChangeCompositingHint;

  if (box.HasLayer() && box.Layer()->Has3DTransformedDescendant()) {
    if (style.HasPerspective())
      compositing_reasons |= kCompositingReasonPerspectiveWith3DDescendants;
    if (style.UsedTransformStyle3D() == ETransformStyle3D::kPreserve3d)
      compositing_reasons |= kCompositingReasonPreserve3DWith3DDescendants;
  }

  return compositing_reasons;
}

static FloatPoint3D TransformOrigin(const LayoutBox& box) {
  const ComputedStyle& style = box.StyleRef();
  // Transform origin has no effect without a transform or motion path.
  if (!style.HasTransform())
    return FloatPoint3D();
  FloatSize border_box_size(box.Size());
  return FloatPoint3D(
      FloatValueForLength(style.TransformOriginX(), border_box_size.Width()),
      FloatValueForLength(style.TransformOriginY(), border_box_size.Height()),
      style.TransformOriginZ());
}

static bool NeedsTransform(const LayoutObject& object) {
  if (!object.IsBox())
    return false;
  return object.StyleRef().HasTransform() || object.StyleRef().Preserves3D() ||
         CompositingReasonsForTransform(ToLayoutBox(object)) !=
             kCompositingReasonNone;
}

void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
  if (object_.IsSVGChild()) {
    UpdateTransformForNonRootSVG();
    return;
  }

  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    const ComputedStyle& style = object_.StyleRef();
    // A transform node is allocated for transforms, preserves-3d and any
    // direct compositing reason. The latter is required because this is the
    // only way to represent compositing both an element and its stacking
    // descendants.
    if (NeedsTransform(object_)) {
      auto& box = ToLayoutBox(object_);

      CompositingReasons compositing_reasons =
          CompositingReasonsForTransform(box);

      TransformationMatrix matrix;
      style.ApplyTransform(
          matrix, box.Size(), ComputedStyle::kExcludeTransformOrigin,
          ComputedStyle::kIncludeMotionPath,
          ComputedStyle::kIncludeIndependentTransformProperties);

      // TODO(trchen): transform-style should only be respected if a
      // PaintLayer is created. If a node with transform-style: preserve-3d
      // does not exist in an existing rendering context, it establishes a new
      // one.
      unsigned rendering_context_id = context_.current.rendering_context_id;
      if (style.Preserves3D() && !rendering_context_id)
        rendering_context_id = PtrHash<const LayoutObject>::GetHash(&object_);

      auto result = properties_->UpdateTransform(
          context_.current.transform, matrix, TransformOrigin(box),
          context_.current.should_flatten_inherited_transform,
          rendering_context_id, compositing_reasons,
          CompositorElementIdFromUniqueObjectId(
              object_.UniqueId(), CompositorElementIdNamespace::kPrimary));
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      full_context_.force_subtree_update |= properties_->ClearTransform();
    }
  }

  if (properties_->Transform()) {
    context_.current.transform = properties_->Transform();
    if (object_.StyleRef().Preserves3D()) {
      context_.current.rendering_context_id =
          properties_->Transform()->RenderingContextId();
      context_.current.should_flatten_inherited_transform = false;
    } else {
      context_.current.rendering_context_id = 0;
      context_.current.should_flatten_inherited_transform = true;
    }
  }
}

static bool ComputeMaskParameters(IntRect& mask_clip,
                                  ColorFilter& mask_color_filter,
                                  const LayoutObject& object,
                                  const LayoutPoint& paint_offset) {
  DCHECK(object.IsBoxModelObject() || object.IsSVGChild());
  const ComputedStyle& style = object.StyleRef();

  if (object.IsSVGChild()) {
    SVGResources* resources =
        SVGResourcesCache::CachedResourcesForLayoutObject(&object);
    LayoutSVGResourceMasker* masker = resources ? resources->Masker() : nullptr;
    if (!masker)
      return false;
    mask_clip = EnclosingIntRect(object.ObjectBoundingBox());
    mask_color_filter = masker->Style()->SvgStyle().MaskType() == MT_LUMINANCE
                            ? kColorFilterLuminanceToAlpha
                            : kColorFilterNone;
    return true;
  }
  if (!style.HasMask())
    return false;

  LayoutRect maximum_mask_region;
  // For HTML/CSS objects, the extent of the mask is known as "mask
  // painting area", which is determined by CSS mask-clip property.
  // We don't implement mask-clip:margin-box or no-clip currently,
  // so the maximum we can get is border-box.
  if (object.IsBox()) {
    maximum_mask_region = ToLayoutBox(object).BorderBoxRect();
  } else {
    // For inline elements, depends on the value of box-decoration-break
    // there could be one box in multiple fragments or multiple boxes.
    // Either way here we are only interested in the bounding box of them.
    DCHECK(object.IsLayoutInline());
    maximum_mask_region = ToLayoutInline(object).LinesBoundingBox();
  }
  if (style.HasMaskBoxImageOutsets())
    maximum_mask_region.Expand(style.MaskBoxImageOutsets());
  maximum_mask_region.MoveBy(paint_offset);
  mask_clip = PixelSnappedIntRect(maximum_mask_region);
  mask_color_filter = kColorFilterNone;
  return true;
}

static bool NeedsEffect(const LayoutObject& object) {
  const ComputedStyle& style = object.StyleRef();

  const bool is_css_isolated_group =
      object.IsBoxModelObject() && style.IsStackingContext();

  if (!is_css_isolated_group && !object.IsSVGChild())
    return false;

  if (object.IsSVG()) {
    // This handles SVGRoot objects which have PaintLayers.
    if (object.IsSVGRoot() && object.HasNonIsolatedBlendingDescendants())
      return true;
    if (SVGLayoutSupport::IsIsolationRequired(&object))
      return true;
  } else if (object.IsBoxModelObject()) {
    if (PaintLayer* layer = ToLayoutBoxModelObject(object).Layer()) {
      if (layer->HasNonIsolatedDescendantWithBlendMode())
        return true;
    }
  }

  SkBlendMode blend_mode = object.IsBlendingAllowed()
                               ? WebCoreCompositeToSkiaComposite(
                                     kCompositeSourceOver, style.BlendMode())
                               : SkBlendMode::kSrcOver;
  if (blend_mode != SkBlendMode::kSrcOver)
    return true;

  float opacity = style.Opacity();
  if (opacity != 1.0f)
    return true;

  if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(style))
    return true;

  if (object.IsSVGChild()) {
    if (SVGResources* resources =
            SVGResourcesCache::CachedResourcesForLayoutObject(&object)) {
      if (resources->Masker())
        return true;
    }
  }

  if (object.StyleRef().HasMask())
    return true;

  return false;
}

void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
  DCHECK(properties_);
  const ComputedStyle& style = object_.StyleRef();

  // TODO(trchen): Can't omit effect node if we have 3D children.
  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    const ClipPaintPropertyNode* output_clip = nullptr;
    bool local_clip_added_or_removed = false;
    bool local_clip_changed = false;
    if (NeedsEffect(object_)) {
      // We may begin to composite our subtree prior to an animation starts,
      // but a compositor element ID is only needed when an animation is
      // current.
      CompositingReasons compositing_reasons = kCompositingReasonNone;
      if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(
              style)) {
        compositing_reasons = kCompositingReasonActiveAnimation;
      }

      IntRect mask_clip;
      ColorFilter mask_color_filter;
      bool has_mask = ComputeMaskParameters(
          mask_clip, mask_color_filter, object_, context_.current.paint_offset);
      if (has_mask &&
          // TODO(crbug.com/768691): Remove the following condition after mask
          // clip doesn't fail fast/borders/inline-mask-overlay-image-outset-
          // vertical-rl.html.
          RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
        FloatRoundedRect rounded_mask_clip(mask_clip);
        if (properties_->MaskClip() &&
            rounded_mask_clip != properties_->MaskClip()->ClipRect())
          local_clip_changed = true;
        auto result = properties_->UpdateMaskClip(context_.current.clip,
                                                  context_.current.transform,
                                                  FloatRoundedRect(mask_clip));
        local_clip_added_or_removed |= result.NewNodeCreated();
        output_clip = properties_->MaskClip();
      } else {
        full_context_.force_subtree_update |= properties_->ClearMaskClip();
      }

      SkBlendMode blend_mode =
          object_.IsBlendingAllowed()
              ? WebCoreCompositeToSkiaComposite(kCompositeSourceOver,
                                                style.BlendMode())
              : SkBlendMode::kSrcOver;

      auto result = properties_->UpdateEffect(
          context_.current_effect, context_.current.transform, output_clip,
          kColorFilterNone, CompositorFilterOperations(), style.Opacity(),
          blend_mode, compositing_reasons,
          CompositorElementIdFromUniqueObjectId(
              object_.UniqueId(), CompositorElementIdNamespace::kPrimary));
      full_context_.force_subtree_update |= result.NewNodeCreated();
      if (has_mask) {
        auto result = properties_->UpdateMask(
            properties_->Effect(), context_.current.transform, output_clip,
            mask_color_filter, CompositorFilterOperations(), 1.f,
            SkBlendMode::kDstIn, kCompositingReasonNone,
            CompositorElementIdFromUniqueObjectId(
                object_.UniqueId(), CompositorElementIdNamespace::kEffectMask));
        full_context_.force_subtree_update |= result.NewNodeCreated();
      } else {
        full_context_.force_subtree_update |= properties_->ClearMask();
      }
    } else {
      full_context_.force_subtree_update |= properties_->ClearEffect();
      full_context_.force_subtree_update |= properties_->ClearMask();
      local_clip_added_or_removed |= properties_->ClearMaskClip();
    }
    full_context_.force_subtree_update |= local_clip_added_or_removed;
    full_context_.clip_changed |=
        local_clip_changed || local_clip_added_or_removed;
  }

  if (properties_->Effect()) {
    context_.current_effect = properties_->Effect();
    if (properties_->MaskClip()) {
      context_.current.clip = context_.absolute_position.clip =
          context_.fixed_position.clip = properties_->MaskClip();
    }
  }
}

static bool NeedsFilter(const LayoutObject& object) {
  // TODO(trchen): SVG caches filters in SVGResources. Implement it.
  return object.IsBoxModelObject() && ToLayoutBoxModelObject(object).Layer() &&
         (object.StyleRef().HasFilter() || object.HasReflection());
}

void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
  DCHECK(properties_);
  const ComputedStyle& style = object_.StyleRef();

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    if (NeedsFilter(object_)) {
      CompositorFilterOperations filter =
          ToLayoutBoxModelObject(object_)
              .Layer()
              ->CreateCompositorFilterOperationsForFilter(style);

      // The CSS filter spec didn't specify how filters interact with overflow
      // clips. The implementation here mimics the old Blink/WebKit behavior for
      // backward compatibility.
      // Basically the output of the filter will be affected by clips that
      // applies to the current element. The descendants that paints into the
      // input of the filter ignores any clips collected so far. For example:
      // <div style="overflow:scroll">
      //   <div style="filter:blur(1px);">
      //     <div>A</div>
      //     <div style="position:absolute;">B</div>
      //   </div>
      // </div>
      // In this example "A" should be clipped if the filter was not present.
      // With the filter, "A" will be rastered without clipping, but instead
      // the blurred result will be clipped.
      // On the other hand, "B" should not be clipped because the overflow clip
      // is not in its containing block chain, but as the filter output will be
      // clipped, so a blurred "B" may still be invisible.
      const ClipPaintPropertyNode* output_clip = context_.current.clip;

      // TODO(trchen): A filter may contain spatial operations such that an
      // output pixel may depend on an input pixel outside of the output clip.
      // We should generate a special clip node to represent this expansion.

      // We may begin to composite our subtree prior to an animation starts,
      // but a compositor element ID is only needed when an animation is
      // current.
      CompositingReasons compositing_reasons =
          CompositingReasonFinder::RequiresCompositingForFilterAnimation(style)
              ? kCompositingReasonActiveAnimation
              : kCompositingReasonNone;
      DCHECK(!style.HasCurrentFilterAnimation() ||
             compositing_reasons != kCompositingReasonNone);

      auto result = properties_->UpdateFilter(
          context_.current_effect, context_.current.transform, output_clip,
          kColorFilterNone, std::move(filter), 1.f, SkBlendMode::kSrcOver,
          compositing_reasons,
          CompositorElementIdFromUniqueObjectId(
              object_.UniqueId(), CompositorElementIdNamespace::kEffectFilter),
          FloatPoint(context_.current.paint_offset));
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      full_context_.force_subtree_update |= properties_->ClearFilter();
    }
  }

  if (properties_->Filter()) {
    context_.current_effect = properties_->Filter();
    // TODO(trchen): Change input clip to expansion hint once implemented.
    const ClipPaintPropertyNode* input_clip =
        properties_->Filter()->OutputClip();
    context_.current.clip = context_.absolute_position.clip =
        context_.fixed_position.clip = input_clip;
  }
}

static bool NeedsFragmentation(const LayoutObject& object,
                               const PaintLayer& painting_layer) {
  return painting_layer.ShouldFragmentCompositedBounds();
}

static bool NeedsFragmentationClip(const LayoutObject& object,
                                   const PaintLayer& painting_layer) {
  return object.HasLayer() && NeedsFragmentation(object, painting_layer);
}

void FragmentPaintPropertyTreeBuilder::UpdateFragmentClip(
    const PaintLayer& painting_layer) {
  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    bool local_clip_added_or_removed = false;
    bool local_clip_changed = false;
    // It's possible to still have no clips even if NeedsFragmentationClip is
    // true, in the case when the FragmentainerIterator returns none.
    if (NeedsFragmentationClip(object_, painting_layer) &&
        context_.fragment_clip) {
      LayoutRect clip_rect(*context_.fragment_clip);

      FloatRoundedRect rounded_clip_rect((FloatRect(clip_rect)));

      if (properties_->FragmentClip() &&
          properties_->FragmentClip()->ClipRect() != rounded_clip_rect)
        local_clip_changed = true;

      auto result = properties_->UpdateFragmentClip(
          context_.current.clip, context_.current.transform, rounded_clip_rect);
      local_clip_added_or_removed |= result.NewNodeCreated();
    } else {
      local_clip_added_or_removed |= properties_->ClearFragmentClip();
    }
    full_context_.force_subtree_update |= local_clip_added_or_removed;
    full_context_.clip_changed |=
        local_clip_changed || local_clip_added_or_removed;
  }
}

static bool NeedsCssClip(const LayoutObject& object) {
  return object.HasClip();
}

void FragmentPaintPropertyTreeBuilder::UpdateCssClip() {
  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    bool local_clip_added_or_removed = false;
    bool local_clip_changed = false;
    if (NeedsCssClip(object_)) {
      // Create clip node for descendants that are not fixed position.
      // We don't have to setup context.absolutePosition.clip here because this
      // object must be a container for absolute position descendants, and will
      // copy from in-flow context later at updateOutOfFlowContext() step.
      DCHECK(object_.CanContainAbsolutePositionObjects());
      LayoutRect clip_rect =
          ToLayoutBox(object_).ClipRect(context_.current.paint_offset);

      FloatRoundedRect rounded_clip_rect((FloatRect(clip_rect)));
      if (properties_->CssClip() &&
          properties_->CssClip()->ClipRect() != rounded_clip_rect)
        local_clip_changed = true;

      auto result = properties_->UpdateCssClip(
          context_.current.clip, context_.current.transform,
          FloatRoundedRect(FloatRect(clip_rect)));
      local_clip_added_or_removed |= result.NewNodeCreated();
    } else {
      local_clip_added_or_removed |= properties_->ClearCssClip();
    }
    full_context_.force_subtree_update |= local_clip_added_or_removed;
    full_context_.clip_changed |=
        local_clip_changed || local_clip_added_or_removed;
  }

  if (properties_->CssClip())
    context_.current.clip = properties_->CssClip();
}

void FragmentPaintPropertyTreeBuilder::UpdateLocalBorderBoxContext() {
  if (!object_.NeedsPaintPropertyUpdate() &&
      !full_context_.force_subtree_update)
    return;

  auto* rare_paint_data = fragment_data_.GetRarePaintData();

  if (!object_.HasLayer() && !NeedsPaintOffsetTranslation(object_)) {
    if (rare_paint_data)
      rare_paint_data->ClearLocalBorderBoxProperties();
  } else {
    DCHECK(rare_paint_data);
    const ClipPaintPropertyNode* clip = context_.current.clip;
    if (rare_paint_data->PaintProperties() &&
        rare_paint_data->PaintProperties()->FragmentClip()) {
      clip = rare_paint_data->PaintProperties()->FragmentClip();
    }

    PropertyTreeState local_border_box = PropertyTreeState(
        context_.current.transform, clip, context_.current_effect);

    rare_paint_data->SetLocalBorderBoxProperties(local_border_box);
  }
}

static bool NeedsOverflowClip(const LayoutObject& object) {
  return object.IsBox() && ToLayoutBox(object).ShouldClipOverflow();
}

static bool NeedsControlClipFragmentationAdjustment(const LayoutBox& box) {
  return box.HasControlClip() && !box.Layer() &&
         box.PaintingLayer()->EnclosingPaginationLayer();
}

static LayoutPoint VisualOffsetFromPaintOffsetRoot(
    const PaintPropertyTreeBuilderFragmentContext& context,
    const PaintLayer* child) {
  const LayoutObject* paint_offset_root = context.current.paint_offset_root;
  PaintLayer* painting_layer = paint_offset_root->PaintingLayer();
  LayoutPoint result = child->VisualOffsetFromAncestor(painting_layer);
  if (!paint_offset_root->HasLayer()) {
    result.Move(-paint_offset_root->OffsetFromAncestorContainer(
        &painting_layer->GetLayoutObject()));
  }

  // Don't include scroll offset of paint_offset_root. Any scroll is
  // already included in a separate transform node.
  if (paint_offset_root->HasOverflowClip())
    result += ToLayoutBox(paint_offset_root)->ScrolledContentOffset();
  return result;
}

void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    bool local_clip_added_or_removed = false;
    bool local_clip_changed = false;
    if (NeedsOverflowClip(object_)) {
      const LayoutBox& box = ToLayoutBox(object_);
      LayoutRect clip_rect;
      clip_rect = box.OverflowClipRect(context_.current.paint_offset);

      const auto* current_clip = context_.current.clip;
      if (box.StyleRef().HasBorderRadius()) {
        auto inner_border = box.StyleRef().GetRoundedInnerBorderFor(
            LayoutRect(context_.current.paint_offset, box.Size()));
        auto result = properties_->UpdateInnerBorderRadiusClip(
            context_.current.clip, context_.current.transform, inner_border);
        local_clip_added_or_removed |= result.NewNodeCreated();
        current_clip = properties_->InnerBorderRadiusClip();
      } else {
        local_clip_added_or_removed |=
            properties_->ClearInnerBorderRadiusClip();
      }

      FloatRoundedRect clipping_rect((FloatRect(clip_rect)));
      if (properties_->OverflowClip() &&
          clipping_rect != properties_->OverflowClip()->ClipRect()) {
        local_clip_changed = true;
      }

      auto result = properties_->UpdateOverflowClip(
          current_clip, context_.current.transform,
          FloatRoundedRect(FloatRect(clip_rect)));
      local_clip_added_or_removed |= result.NewNodeCreated();
    } else {
      local_clip_added_or_removed |= properties_->ClearInnerBorderRadiusClip();
      local_clip_added_or_removed |= properties_->ClearOverflowClip();
    }
    full_context_.force_subtree_update |= local_clip_added_or_removed;
    full_context_.clip_changed |=
        local_clip_changed || local_clip_added_or_removed;
  }

  if (properties_->OverflowClip())
    context_.current.clip = properties_->OverflowClip();
}

static FloatPoint PerspectiveOrigin(const LayoutBox& box) {
  const ComputedStyle& style = box.StyleRef();
  // Perspective origin has no effect without perspective.
  DCHECK(style.HasPerspective());
  FloatSize border_box_size(box.Size());
  return FloatPoint(
      FloatValueForLength(style.PerspectiveOriginX(), border_box_size.Width()),
      FloatValueForLength(style.PerspectiveOriginY(),
                          border_box_size.Height()));
}

static bool NeedsPerspective(const LayoutObject& object) {
  return object.IsBox() && object.StyleRef().HasPerspective();
}

void FragmentPaintPropertyTreeBuilder::UpdatePerspective() {
  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    if (NeedsPerspective(object_)) {
      const ComputedStyle& style = object_.StyleRef();
      // The perspective node must not flatten (else nothing will get
      // perspective), but it should still extend the rendering context as
      // most transform nodes do.
      TransformationMatrix matrix =
          TransformationMatrix().ApplyPerspective(style.Perspective());
      FloatPoint3D origin = PerspectiveOrigin(ToLayoutBox(object_)) +
                            ToLayoutSize(context_.current.paint_offset);
      auto result = properties_->UpdatePerspective(
          context_.current.transform, matrix, origin,
          context_.current.should_flatten_inherited_transform,
          context_.current.rendering_context_id);
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      full_context_.force_subtree_update |= properties_->ClearPerspective();
    }
  }

  if (properties_->Perspective()) {
    context_.current.transform = properties_->Perspective();
    context_.current.should_flatten_inherited_transform = false;
  }
}

void FragmentPaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform() {
  DCHECK(properties_);
  if (!object_.IsSVGRoot())
    return;

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    AffineTransform transform_to_border_box =
        SVGRootPainter(ToLayoutSVGRoot(object_))
            .TransformToPixelSnappedBorderBox(context_.current.paint_offset);
    if (!transform_to_border_box.IsIdentity() &&
        NeedsSVGLocalToBorderBoxTransform(object_)) {
      auto result = properties_->UpdateSvgLocalToBorderBoxTransform(
          context_.current.transform, transform_to_border_box, FloatPoint3D());
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      full_context_.force_subtree_update |=
          properties_->ClearSvgLocalToBorderBoxTransform();
    }
  }

  if (properties_->SvgLocalToBorderBoxTransform()) {
    context_.current.transform = properties_->SvgLocalToBorderBoxTransform();
    context_.current.should_flatten_inherited_transform = false;
    context_.current.rendering_context_id = 0;
  }
  // The paint offset is included in |transformToBorderBox| so SVG does not need
  // to handle paint offset internally.
  context_.current.paint_offset = LayoutPoint();
}

static MainThreadScrollingReasons GetMainThreadScrollingReasons(
    const LayoutObject& object,
    MainThreadScrollingReasons ancestor_reasons) {
  // The current main thread scrolling reasons implementation only changes
  // reasons at frame boundaries, so we can early-out when not at a LayoutView.
  // TODO(pdr): Need to find a solution to the style-related main thread
  // scrolling reasons such as opacity and transform which violate this.
  if (!object.IsLayoutView())
    return ancestor_reasons;
  return GetMainThreadScrollingReasons(*object.GetFrameView(),
                                       ancestor_reasons);
}

void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
  DCHECK(properties_);

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    if (NeedsScrollNode(object_)) {
      const LayoutBox& box = ToLayoutBox(object_);
      auto* scrollable_area = box.GetScrollableArea();

      // The container bounds are snapped to integers to match the equivalent
      // bounds on cc::ScrollNode. The offset is snapped to match the current
      // integer offsets used in CompositedLayerMapping.
      auto container_rect = PixelSnappedIntRect(
          box.OverflowClipRect(context_.current.paint_offset));

      IntRect contents_rect(-scrollable_area->ScrollOrigin(),
                            scrollable_area->ContentsSize());
      contents_rect.MoveBy(container_rect.Location());
      // In flipped blocks writing mode, if there is scrollbar on the right,
      // we move the contents to the left with extra amount of ScrollTranslation
      // (-VerticalScrollbarWidth, 0). As contents_rect is in the space of
      // ScrollTranslation, we need to compensate the extra ScrollTranslation
      // to get correct contents_rect origin.
      if (box.HasFlippedBlocksWritingMode())
        contents_rect.Move(box.VerticalScrollbarWidth(), 0);

      bool user_scrollable_horizontal =
          scrollable_area->UserInputScrollable(kHorizontalScrollbar);
      bool user_scrollable_vertical =
          scrollable_area->UserInputScrollable(kVerticalScrollbar);

      auto ancestor_reasons =
          context_.current.scroll->GetMainThreadScrollingReasons();
      auto reasons = GetMainThreadScrollingReasons(object_, ancestor_reasons);

      // Main thread scrolling reasons depend on their ancestor's reasons
      // so ensure the entire subtree is updated when reasons change.
      if (auto* existing_scroll = properties_->Scroll()) {
        if (existing_scroll->GetMainThreadScrollingReasons() != reasons)
          full_context_.force_subtree_update = true;
      }

      auto element_id = scrollable_area->GetCompositorElementId();

      // TODO(pdr): Set the correct compositing reasons here.
      auto result = properties_->UpdateScroll(
          context_.current.scroll, container_rect, contents_rect,
          user_scrollable_horizontal, user_scrollable_vertical, reasons,
          element_id);
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      // Ensure pre-existing properties are cleared.
      full_context_.force_subtree_update |= properties_->ClearScroll();
    }

    // A scroll translation node is created for static offset (e.g., overflow
    // hidden with scroll offset) or cases that scroll and have a scroll node.
    if (NeedsScrollOrScrollTranslation(object_)) {
      const LayoutBox& box = ToLayoutBox(object_);
      IntSize scroll_offset = box.ScrolledContentOffset();
      TransformationMatrix scroll_offset_matrix =
          TransformationMatrix().Translate(-scroll_offset.Width(),
                                           -scroll_offset.Height());
      auto result = properties_->UpdateScrollTranslation(
          context_.current.transform, scroll_offset_matrix, FloatPoint3D(),
          context_.current.should_flatten_inherited_transform,
          context_.current.rendering_context_id, kCompositingReasonNone,
          CompositorElementId(), properties_->Scroll());
      full_context_.force_subtree_update |= result.NewNodeCreated();
    } else {
      // Ensure pre-existing properties are cleared.
      full_context_.force_subtree_update |=
          properties_->ClearScrollTranslation();
    }
  }

  if (properties_->Scroll())
    context_.current.scroll = properties_->Scroll();
  if (properties_->ScrollTranslation()) {
    context_.current.transform = properties_->ScrollTranslation();
    context_.current.should_flatten_inherited_transform = false;
  }
}

void FragmentPaintPropertyTreeBuilder::UpdateOutOfFlowContext() {
  if (!object_.IsBoxModelObject() && !properties_)
    return;

  if (object_.IsLayoutBlock())
    context_.paint_offset_for_float = context_.current.paint_offset;

  if (object_.CanContainAbsolutePositionObjects())
    context_.absolute_position = context_.current;

  if (object_.IsLayoutView()) {
    if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
      const auto* initial_fixed_transform = context_.fixed_position.transform;
      const auto* initial_fixed_scroll = context_.fixed_position.scroll;

      context_.fixed_position = context_.current;

      // Fixed position transform and scroll nodes should not be affected.
      context_.fixed_position.transform = initial_fixed_transform;
      context_.fixed_position.scroll = initial_fixed_scroll;
    }
  } else if (object_.CanContainFixedPositionObjects()) {
    context_.fixed_position = context_.current;
    context_.fixed_position.fixed_position_children_fixed_to_root = false;
  } else if (properties_ && properties_->CssClip()) {
    // CSS clip applies to all descendants, even if this object is not a
    // containing block ancestor of the descendant. It is okay for
    // absolute-position descendants because having CSS clip implies being
    // absolute position container. However for fixed-position descendants we
    // need to insert the clip here if we are not a containing block ancestor of
    // them.
    auto* css_clip = properties_->CssClip();

    // Before we actually create anything, check whether in-flow context and
    // fixed-position context has exactly the same clip. Reuse if possible.
    if (context_.fixed_position.clip == css_clip->Parent()) {
      context_.fixed_position.clip = css_clip;
    } else {
      if (object_.NeedsPaintPropertyUpdate() ||
          full_context_.force_subtree_update) {
        auto result = properties_->UpdateCssClipFixedPosition(
            context_.fixed_position.clip,
            const_cast<TransformPaintPropertyNode*>(
                css_clip->LocalTransformSpace()),
            css_clip->ClipRect());
        full_context_.force_subtree_update |= result.NewNodeCreated();
      }
      if (properties_->CssClipFixedPosition())
        context_.fixed_position.clip = properties_->CssClipFixedPosition();
      return;
    }
  }

  if (object_.NeedsPaintPropertyUpdate() ||
      full_context_.force_subtree_update) {
    if (properties_) {
      full_context_.force_subtree_update |=
          properties_->ClearCssClipFixedPosition();
    }
  }
}

static LayoutRect BoundingBoxInPaginationContainer(
    const LayoutObject& object,
    const PaintLayer& enclosing_pagination_layer) {
  // Non-boxes that have no layer paint in the space of their containing block.
  if (!object.IsBox() && !object.HasLayer()) {
    return BoundingBoxInPaginationContainer(*object.ContainingBlock(),
                                            enclosing_pagination_layer);
  }

  LayoutRect object_bounding_box_in_flow_thread;
  if (object.HasLayer()) {
    PaintLayer* paint_layer = ToLayoutBoxModelObject(object).Layer();
    object_bounding_box_in_flow_thread =
        paint_layer->PhysicalBoundingBox(&enclosing_pagination_layer);
  } else {
    // Compute the bounding box without transforms.
    // The object is guaranteed to be a box due to the logic above.
    DCHECK(object.IsBox());
    object_bounding_box_in_flow_thread = ToLayoutBox(object).BorderBoxRect();
    TransformState transform_state(
        TransformState::kApplyTransformDirection,
        FloatPoint(object_bounding_box_in_flow_thread.Location()));
    object.MapLocalToAncestor(&enclosing_pagination_layer.GetLayoutObject(),
                              transform_state, kApplyContainerFlip);
    transform_state.Flatten();
    object_bounding_box_in_flow_thread.SetLocation(
        LayoutPoint(transform_state.LastPlanarPoint()));
  }

  return object_bounding_box_in_flow_thread;
}

void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
  // Paint offsets for fragmented content are computed from scratch.
  if (context_.fragment_clip &&
      // Except if the paint_offset_root is below the pagination container,
      // in which case fragmentation offsets are already baked into the paint
      // offset transform for paint_offset_root.
      !context_.current.paint_offset_root->PaintingLayer()
           ->EnclosingPaginationLayer()) {
    PaintLayer* paint_layer = object_.PaintingLayer();
    PaintLayer* enclosing_pagination_layer =
        paint_layer->EnclosingPaginationLayer();
    DCHECK(enclosing_pagination_layer);

    // Set fragment visual paint offset.
    LayoutPoint paint_offset =
        BoundingBoxInPaginationContainer(object_, *enclosing_pagination_layer)
            .Location();

    paint_offset.MoveBy(fragment_data_.GetRarePaintData()->PaginationOffset());
    paint_offset.MoveBy(
        VisualOffsetFromPaintOffsetRoot(context_, enclosing_pagination_layer));

    // The paint offset root can have a subpixel paint offset adjustment.
    // The paint offset root always has one fragment.
    paint_offset.MoveBy(
        context_.current.paint_offset_root->FirstFragment().PaintOffset());

    context_.current.paint_offset = paint_offset;

    return;
  }

  if (object_.IsFloating())
    context_.current.paint_offset = context_.paint_offset_for_float;

  // Multicolumn spanners are painted starting at the multicolumn container (but
  // still inherit properties in layout-tree order) so reset the paint offset.
  if (object_.IsColumnSpanAll()) {
    context_.current.paint_offset =
        object_.Container()->FirstFragment().PaintOffset();
  }

  if (object_.IsBoxModelObject()) {
    const LayoutBoxModelObject& box_model_object =
        ToLayoutBoxModelObject(object_);
    switch (box_model_object.StyleRef().GetPosition()) {
      case EPosition::kStatic:
        break;
      case EPosition::kRelative:
        context_.current.paint_offset +=
            box_model_object.OffsetForInFlowPosition();
        break;
      case EPosition::kAbsolute: {
        DCHECK(full_context_.container_for_absolute_position ==
               box_model_object.Container());
        context_.current = context_.absolute_position;

        // Absolutely positioned content in an inline should be positioned
        // relative to the inline.
        const auto* container = full_context_.container_for_absolute_position;
        if (container && container->IsInFlowPositioned() &&
            container->IsLayoutInline()) {
          DCHECK(box_model_object.IsBox());
          context_.current.paint_offset +=
              ToLayoutInline(container)->OffsetForInFlowPositionedInline(
                  ToLayoutBox(box_model_object));
        }
        break;
      }
      case EPosition::kSticky:
        context_.current.paint_offset +=
            box_model_object.OffsetForInFlowPosition();
        break;
      case EPosition::kFixed:
        context_.current = context_.fixed_position;
        // Fixed-position elements that are fixed to the vieport have a
        // transform above the scroll of the LayoutView. Child content is
        // relative to that transform, and hence the fixed-position element.
        if (context_.fixed_position.fixed_position_children_fixed_to_root)
          context_.current.paint_offset_root = &box_model_object;
        break;
      default:
        NOTREACHED();
    }
  }

  if (object_.IsBox()) {
    // TODO(pdr): Several calls in this function walk back up the tree to
    // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*).
    // The containing block and other containers can be stored on
    // PaintPropertyTreeBuilderFragmentContext instead of recomputing them.
    context_.current.paint_offset.MoveBy(
        ToLayoutBox(object_).PhysicalLocation());
    // This is a weird quirk that table cells paint as children of table rows,
    // but their location have the row's location baked-in.
    // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
    if (object_.IsTableCell()) {
      LayoutObject* parent_row = object_.Parent();
      DCHECK(parent_row && parent_row->IsTableRow());
      context_.current.paint_offset.MoveBy(
          -ToLayoutBox(parent_row)->PhysicalLocation());
    }
  }
}

static void SetNeedsPaintPropertyUpdateIfNeeded(const LayoutObject& object) {
  if (!object.IsBoxModelObject())
    return;

  const LayoutBoxModelObject& box_model_object = ToLayoutBoxModelObject(object);
  if (box_model_object.Layer() &&
      box_model_object.Layer()->ShouldFragmentCompositedBounds()) {
    // Always force-update properties for fragmented content.
    // TODO(chrishtr): find ways to optimize this in the future.
    // It may suffice to compare previous and current visual overflow,
    // but we do not currenly cache that on the LayoutObject or PaintLayer.
    object.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
    return;
  }

  if (!object.IsBox())
    return;

  const LayoutBox& box = ToLayoutBox(object);

  // Always force-update properties for fragmented content. Boxes with
  // control clip have a fragment-aware offset.
  if (NeedsControlClipFragmentationAdjustment(box)) {
    box.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
    return;
  }

  if (box.Size() == box.PreviousSize())
    return;

  // CSS mask and clip-path comes with an implicit clip to the border box.
  // Currently only SPv2 generate and take advantage of those.
  const bool box_generates_property_nodes_for_mask_and_clip_path =
      RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
      (box.HasMask() || box.HasClipPath());
  // The overflow clip paint property depends on the border box rect through
  // overflowClipRect(). The border box rect's size equals the frame rect's
  // size so we trigger a paint property update when the frame rect changes.
  if (box.ShouldClipOverflow() ||
      // The used value of CSS clip may depend on size of the box, e.g. for
      // clip: rect(auto auto auto -5px).
      box.HasClip() ||
      // Relative lengths (e.g., percentage values) in transform, perspective,
      // transform-origin, and perspective-origin can depend on the size of the
      // frame rect, so force a property update if it changes. TODO(pdr): We
      // only need to update properties if there are relative lengths.
      box.StyleRef().HasTransform() || box.StyleRef().HasPerspective() ||
      box_generates_property_nodes_for_mask_and_clip_path)
    box.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
}

void FragmentPaintPropertyTreeBuilder::UpdateForObjectLocationAndSize(
    Optional<IntPoint>& paint_offset_translation) {
#if DCHECK_IS_ON()
  FindPaintOffsetNeedingUpdateScope check_scope(
      object_, fragment_data_, full_context_.is_actually_needed);
#endif

  UpdatePaintOffset();
  UpdateForPaintOffsetTranslation(paint_offset_translation);

  if (fragment_data_.PaintOffset() != context_.current.paint_offset) {
    // Many paint properties depend on paint offset so we force an update of
    // the entire subtree on paint offset changes.
    full_context_.force_subtree_update = true;

    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
      object_.GetMutableForPainting().SetShouldDoFullPaintInvalidation(
          PaintInvalidationReason::kGeometry);
    }
    fragment_data_.SetPaintOffset(context_.current.paint_offset);
  }

  if (paint_offset_translation)
    context_.current.paint_offset_root = &ToLayoutBoxModelObject(object_);

  SetNeedsPaintPropertyUpdateIfNeeded(object_);
}

void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
  // This is not in FindObjectPropertiesNeedingUpdateScope because paint offset
  // can change without NeedsPaintPropertyUpdate.
  Optional<IntPoint> paint_offset_translation;
  UpdateForObjectLocationAndSize(paint_offset_translation);

  if (properties_) {
    // TODO(wangxianzhu): Put these in FindObjectPropertiesNeedingUpdateScope.
    UpdateFragmentClip(*full_context_.painting_layer);
    UpdatePaintOffsetTranslation(paint_offset_translation);
  }

#if DCHECK_IS_ON()
  FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(
      object_, fragment_data_, full_context_.force_subtree_update);
#endif

  if (properties_) {
    UpdateTransform();
    UpdateCssClip();
    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
      UpdateEffect();
    UpdateFilter();
  }
  UpdateLocalBorderBoxContext();
}

void FragmentPaintPropertyTreeBuilder::UpdateForChildren() {
#if DCHECK_IS_ON()
  FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(
      object_, fragment_data_, full_context_.force_subtree_update);
#endif

  if (properties_) {
    UpdateOverflowClip();
    UpdatePerspective();
    UpdateSvgLocalToBorderBoxTransform();
    UpdateScrollAndScrollTranslation();
  }
  UpdateOutOfFlowContext();
}

}  // namespace

// Match |fragment_clip| against an intersecting one from the parent contexts,
// if any, to allow for correct transform and effect parenting of fragments.
PaintPropertyTreeBuilderFragmentContext ContextForFragment(
    const LayoutRect& fragment_clip,
    const Vector<PaintPropertyTreeBuilderFragmentContext, 1>&
        parent_fragments) {
  // Find a fragment whose clip intersects this one, if any.
  for (auto& fragment_context : parent_fragments) {
    if (!fragment_context.fragment_clip ||
        fragment_clip.Intersects(*fragment_context.fragment_clip)) {
      PaintPropertyTreeBuilderFragmentContext context(fragment_context);
      context.fragment_clip = fragment_clip;
      return context;
    }
  }

  // Otherwise return a new fragment parented at the first parent fragment.
  if (parent_fragments.IsEmpty()) {
    PaintPropertyTreeBuilderFragmentContext context;
    context.fragment_clip = LayoutRect();
    return context;
  }
  PaintPropertyTreeBuilderFragmentContext context(parent_fragments[0]);
  context.fragment_clip = fragment_clip;
  return context;
}

void ObjectPaintPropertyTreeBuilder::InitSingleFragmentFromParent(
    bool needs_paint_properties) {
  FragmentData& first_fragment =
      object_.GetMutableForPainting().FirstFragment();
  first_fragment.ClearNextFragment();
  if (needs_paint_properties)
    first_fragment.EnsureRarePaintData().EnsurePaintProperties();
  if (context_.fragments.IsEmpty()) {
    context_.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());
  } else {
    context_.fragments.resize(1);
    context_.fragments[0].fragment_clip.reset();
  }
}

// Limit the maximum number of fragments, to avoid pathological situations.
static const int kMaxNumFragments = 2000;

void ObjectPaintPropertyTreeBuilder::UpdateFragments() {
  bool needs_paint_properties =
      NeedsPaintOffsetTranslation(object_) || NeedsTransform(object_) ||
      NeedsEffect(object_) || NeedsTransformForNonRootSVG(object_) ||
      NeedsFilter(object_) || NeedsCssClip(object_) ||
      NeedsOverflowClip(object_) || NeedsPerspective(object_) ||
      NeedsSVGLocalToBorderBoxTransform(object_) ||
      NeedsScrollOrScrollTranslation(object_) ||
      NeedsFragmentationClip(object_, *context_.painting_layer);

  bool needs_fragments = NeedsFragmentation(object_, *context_.painting_layer);
  bool had_paint_properties = object_.FirstFragment().PaintProperties();
  if (!needs_paint_properties && !needs_fragments && !object_.HasLayer()) {
    if (had_paint_properties) {
      context_.force_subtree_update = true;
      object_.FirstFragment().GetRarePaintData()->ClearPaintProperties();
    }
    InitSingleFragmentFromParent(needs_paint_properties);
  } else {
    if (!needs_fragments) {
      InitSingleFragmentFromParent(needs_paint_properties);
    } else {
      // We need at least the fragments for all fragmented objects, which store
      // their local border box properties and paint invalidation data (such
      // as paint offset and visual rect) on each fragment.
      PaintLayer* paint_layer = object_.PaintingLayer();
      PaintLayer* enclosing_pagination_layer =
          paint_layer->EnclosingPaginationLayer();

      LayoutRect object_bounding_box_in_flow_thread =
          BoundingBoxInPaginationContainer(object_,
                                           *enclosing_pagination_layer);
      const LayoutFlowThread& flow_thread =
          ToLayoutFlowThread(enclosing_pagination_layer->GetLayoutObject());
      FragmentainerIterator iterator(flow_thread,
                                     object_bounding_box_in_flow_thread);

      Vector<PaintPropertyTreeBuilderFragmentContext> new_fragment_contexts;
      FragmentData* current_fragment_data = nullptr;

      int fragment_count = 0;
      for (; !iterator.AtEnd() && fragment_count < kMaxNumFragments;
           iterator.Advance(), fragment_count++) {
        if (!current_fragment_data) {
          current_fragment_data =
              &object_.GetMutableForPainting().FirstFragment();
        } else {
          current_fragment_data = &current_fragment_data->EnsureNextFragment();
        }

        RarePaintData& rare_paint_data =
            current_fragment_data->EnsureRarePaintData();

        if (needs_paint_properties)
          rare_paint_data.EnsurePaintProperties();

        // 1. Compute clip in flow thread space of the containing flow thread.
        LayoutRect fragment_clip(iterator.ClipRectInFlowThread());
        // 2. Convert #1 to visual coordinates in the space of the flow
        // thread.
        fragment_clip.Move(iterator.PaginationOffset());
        // 3. Adust #2 to visual coordinates in the containing "paint offset"
        // space.
        {
          DCHECK(context_.fragments[0].current.paint_offset_root);
          LayoutPoint pagination_visual_offset =
              VisualOffsetFromPaintOffsetRoot(context_.fragments[0],
                                              enclosing_pagination_layer);

          // Adjust for paint offset of the root, which may have a subpixel
          // component.
          // The paint offset root never has more than one fragment.
          pagination_visual_offset.MoveBy(
              context_.fragments[0]
                  .current.paint_offset_root->FirstFragment()
                  .PaintOffset());

          fragment_clip.MoveBy(pagination_visual_offset);
        }
        // 4. Match to parent fragments from the same containing flow
        // thread.
        new_fragment_contexts.push_back(
            ContextForFragment(fragment_clip, context_.fragments));
        // 5. Save off PaginationOffset (which allows us to adjust
        // logical paint offsets into the space of the current fragment later.

        current_fragment_data->GetRarePaintData()->SetPaginationOffset(
            ToLayoutPoint(iterator.PaginationOffset()));
      }
      if (current_fragment_data) {
        current_fragment_data->ClearNextFragment();
        context_.fragments = new_fragment_contexts;
      } else {
        // This will be an empty fragment - get rid of it?
        InitSingleFragmentFromParent(needs_paint_properties);
      }
    }
  }

  if (object_.IsSVGHiddenContainer()) {
    // SVG resources are painted within one or more other locations in the
    // SVG during paint, and hence have their own independent paint property
    // trees, paint offset, etc.
    context_.fragments.clear();
    context_.fragments.Grow(1);
    PaintPropertyTreeBuilderFragmentContext& fragment_context =
        context_.fragments[0];

    fragment_context.current.paint_offset_root =
        fragment_context.absolute_position.paint_offset_root =
            fragment_context.fixed_position.paint_offset_root = &object_;

    object_.GetMutableForPainting().FirstFragment().ClearNextFragment();
  }
}

static inline bool ObjectTypeMightNeedPaintProperties(
    const LayoutObject& object) {
  return object.IsBoxModelObject() || object.IsSVG() ||
         object.PaintingLayer()->EnclosingPaginationLayer();
}

void ObjectPaintPropertyTreeBuilder::UpdatePaintingLayer() {
  bool changed_painting_layer = false;
  if (object_.HasLayer() &&
      ToLayoutBoxModelObject(object_).HasSelfPaintingLayer()) {
    context_.painting_layer = ToLayoutBoxModelObject(object_).Layer();
    changed_painting_layer = true;
  } else if (object_.IsColumnSpanAll() ||
             object_.IsFloatingWithNonContainingBlockParent()) {
    // See LayoutObject::paintingLayer() for the special-cases of floating under
    // inline and multicolumn.
    context_.painting_layer = object_.PaintingLayer();
    changed_painting_layer = true;
  }
  DCHECK(context_.painting_layer == object_.PaintingLayer());
}

void ObjectPaintPropertyTreeBuilder::UpdateForSelf() {
  UpdatePaintingLayer();

  if (ObjectTypeMightNeedPaintProperties(object_))
    UpdateFragments();
  else
    object_.GetMutableForPainting().FirstFragment().ClearNextFragment();

  auto* fragment_data = &object_.GetMutableForPainting().FirstFragment();
  for (auto& fragment_context : context_.fragments) {
    FragmentPaintPropertyTreeBuilder(object_, context_, fragment_context,
                                     *fragment_data)
        .UpdateForSelf();
    fragment_data = fragment_data->NextFragment();
  }
  DCHECK(!fragment_data);
}

void ObjectPaintPropertyTreeBuilder::UpdateForChildren() {
  if (!ObjectTypeMightNeedPaintProperties(object_))
    return;

  auto* fragment_data = &object_.GetMutableForPainting().FirstFragment();
  for (auto& fragment_context : context_.fragments) {
    FragmentPaintPropertyTreeBuilder(object_, context_, fragment_context,
                                     *fragment_data)
        .UpdateForChildren();
    context_.force_subtree_update |= object_.SubtreeNeedsPaintPropertyUpdate();
    fragment_data = fragment_data->NextFragment();
  }
  DCHECK(!fragment_data);

  if (object_.CanContainAbsolutePositionObjects())
    context_.container_for_absolute_position = &object_;
}

}  // namespace blink
