// Copyright 2014 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 "third_party/blink/renderer/core/paint/box_painter_base.h"

#include "base/optional.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/css/background_color_paint_image_generator.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/box_border_painter.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
#include "third_party/blink/renderer/core/paint/rounded_border_geometry.h"
#include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/shadow_list.h"
#include "third_party/blink/renderer/core/style/style_fetched_image.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/scoped_interpolation_quality.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"

namespace blink {

void BoxPainterBase::PaintFillLayers(const PaintInfo& paint_info,
                                     const Color& c,
                                     const FillLayer& fill_layer,
                                     const PhysicalRect& rect,
                                     BackgroundImageGeometry& geometry,
                                     BackgroundBleedAvoidance bleed) {
  FillLayerOcclusionOutputList reversed_paint_list;
  bool should_draw_background_in_separate_buffer =
      CalculateFillLayerOcclusionCulling(reversed_paint_list, fill_layer);

  // TODO(trchen): We can optimize out isolation group if we have a
  // non-transparent background color and the bottom layer encloses all other
  // layers.
  GraphicsContext& context = paint_info.context;
  if (should_draw_background_in_separate_buffer)
    context.BeginLayer();

  for (auto it = reversed_paint_list.rbegin(); it != reversed_paint_list.rend();
       ++it) {
    PaintFillLayer(paint_info, c, **it, rect, bleed, geometry);
  }

  if (should_draw_background_in_separate_buffer)
    context.EndLayer();
}

namespace {

void ApplySpreadToShadowShape(FloatRoundedRect& shadow_shape, float spread) {
  if (spread == 0)
    return;

  if (spread >= 0)
    shadow_shape.ExpandRadii(spread);
  else
    shadow_shape.ShrinkRadii(-spread);

  if (!shadow_shape.IsRenderable())
    shadow_shape.AdjustRadii();
  shadow_shape.ConstrainRadii();
}

}  // namespace

void BoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info,
                                          const PhysicalRect& paint_rect,
                                          const ComputedStyle& style,
                                          PhysicalBoxSides sides_to_include,
                                          bool background_is_skipped) {
  if (!style.BoxShadow())
    return;
  GraphicsContext& context = info.context;

  FloatRoundedRect border = RoundedBorderGeometry::PixelSnappedRoundedBorder(
      style, paint_rect, sides_to_include);

  bool has_border_radius = style.HasBorderRadius();
  bool has_opaque_background =
      !background_is_skipped &&
      style.VisitedDependentColor(GetCSSPropertyBackgroundColor()).Alpha() ==
          255;

  GraphicsContextStateSaver state_saver(context, false);

  const ShadowList* shadow_list = style.BoxShadow();
  for (wtf_size_t i = shadow_list->Shadows().size(); i--;) {
    const ShadowData& shadow = shadow_list->Shadows()[i];
    if (shadow.Style() != ShadowStyle::kNormal)
      continue;

    FloatSize shadow_offset(shadow.X(), shadow.Y());
    float shadow_blur = shadow.Blur();
    float shadow_spread = shadow.Spread();

    if (shadow_offset.IsZero() && !shadow_blur && !shadow_spread)
      continue;

    const Color& shadow_color = shadow.GetColor().Resolve(
        style.VisitedDependentColor(GetCSSPropertyColor()),
        style.UsedColorScheme());

    FloatRect fill_rect = border.Rect();
    fill_rect.Inflate(shadow_spread);
    if (fill_rect.IsEmpty())
      continue;

    // Save the state and clip, if not already done.
    // The clip does not depend on any shadow-specific properties.
    if (!state_saver.Saved()) {
      state_saver.Save();
      if (has_border_radius) {
        FloatRoundedRect rect_to_clip_out = border;

        // If the box is opaque, it is unnecessary to clip it out. However,
        // doing so saves time when painting the shadow. On the other hand, it
        // introduces subpixel gaps along the corners. Those are avoided by
        // insetting the clipping path by one CSS pixel.
        if (has_opaque_background)
          rect_to_clip_out.InflateWithRadii(-1);

        if (!rect_to_clip_out.IsEmpty())
          context.ClipOutRoundedRect(rect_to_clip_out);
      } else {
        // This IntRect is correct even with fractional shadows, because it is
        // used for the rectangle of the box itself, which is always
        // pixel-aligned.
        FloatRect rect_to_clip_out = border.Rect();

        // If the box is opaque, it is unnecessary to clip it out. However,
        // doing so saves time when painting the shadow. On the other hand, it
        // introduces subpixel gaps along the edges if they are not
        // pixel-aligned. Those are avoided by insetting the clipping path by
        // one CSS pixel.
        if (has_opaque_background)
          rect_to_clip_out.Inflate(-1);

        if (!rect_to_clip_out.IsEmpty())
          context.ClipOut(rect_to_clip_out);
      }
    }

    // Draw only the shadow. If the color of the shadow is transparent we will
    // set an empty draw looper.
    DrawLooperBuilder draw_looper_builder;
    draw_looper_builder.AddShadow(shadow_offset, shadow_blur, shadow_color,
                                  DrawLooperBuilder::kShadowRespectsTransforms,
                                  DrawLooperBuilder::kShadowIgnoresAlpha);
    context.SetDrawLooper(draw_looper_builder.DetachDrawLooper());

    if (has_border_radius) {
      FloatRoundedRect rounded_fill_rect = border;
      rounded_fill_rect.Inflate(shadow_spread);
      ApplySpreadToShadowShape(rounded_fill_rect, shadow_spread);
      context.FillRoundedRect(rounded_fill_rect, Color::kBlack);
    } else {
      context.FillRect(fill_rect, Color::kBlack);
    }
  }
}

void BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
    const PaintInfo& info,
    const PhysicalRect& border_rect,
    const ComputedStyle& style,
    PhysicalBoxSides sides_to_include) {
  if (!style.BoxShadow())
    return;
  auto bounds = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
      style, border_rect, sides_to_include);
  PaintInsetBoxShadow(info, bounds, style, sides_to_include);
}

void BoxPainterBase::PaintInsetBoxShadowWithInnerRect(
    const PaintInfo& info,
    const PhysicalRect& inner_rect,
    const ComputedStyle& style) {
  if (!style.BoxShadow())
    return;
  auto bounds = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
      style, inner_rect, LayoutRectOutsets());
  PaintInsetBoxShadow(info, bounds, style);
}

namespace {

inline FloatRect AreaCastingShadowInHole(const FloatRect& hole_rect,
                                         const ShadowData& shadow) {
  FloatRect bounds(hole_rect);
  bounds.Inflate(shadow.Blur());

  if (shadow.Spread() < 0)
    bounds.Inflate(-shadow.Spread());

  FloatRect offset_bounds = bounds;
  offset_bounds.MoveBy(-shadow.Location());
  return UnionRect(bounds, offset_bounds);
}

void AdjustInnerRectForSideClipping(FloatRect& inner_rect,
                                    const ShadowData& shadow,
                                    PhysicalBoxSides sides_to_include) {
  if (!sides_to_include.left) {
    float extend_by = std::max(shadow.X(), 0.0f) + shadow.Blur();
    inner_rect.Move(-extend_by, 0);
    inner_rect.SetWidth(inner_rect.Width() + extend_by);
  }
  if (!sides_to_include.top) {
    float extend_by = std::max(shadow.Y(), 0.0f) + shadow.Blur();
    inner_rect.Move(0, -extend_by);
    inner_rect.SetHeight(inner_rect.Height() + extend_by);
  }
  if (!sides_to_include.right) {
    float shrink_by = std::min(shadow.X(), 0.0f) - shadow.Blur();
    inner_rect.SetWidth(inner_rect.Width() - shrink_by);
  }
  if (!sides_to_include.bottom) {
    float shrink_by = std::min(shadow.Y(), 0.0f) - shadow.Blur();
    inner_rect.SetHeight(inner_rect.Height() - shrink_by);
  }
}

}  // namespace

void BoxPainterBase::PaintInsetBoxShadow(const PaintInfo& info,
                                         const FloatRoundedRect& bounds,
                                         const ComputedStyle& style,
                                         PhysicalBoxSides sides_to_include) {
  GraphicsContext& context = info.context;

  const ShadowList* shadow_list = style.BoxShadow();
  for (wtf_size_t i = shadow_list->Shadows().size(); i--;) {
    const ShadowData& shadow = shadow_list->Shadows()[i];
    if (shadow.Style() != ShadowStyle::kInset)
      continue;
    if (!shadow.X() && !shadow.Y() && !shadow.Blur() && !shadow.Spread())
      continue;

    const Color& shadow_color = shadow.GetColor().Resolve(
        style.VisitedDependentColor(GetCSSPropertyColor()),
        style.UsedColorScheme());

    FloatRect inner_rect(bounds.Rect());
    inner_rect.Inflate(-shadow.Spread());
    if (inner_rect.IsEmpty()) {
      context.FillRoundedRect(bounds, shadow_color);
      continue;
    }
    AdjustInnerRectForSideClipping(inner_rect, shadow, sides_to_include);

    FloatRoundedRect inner_rounded_rect(inner_rect, bounds.GetRadii());
    GraphicsContextStateSaver state_saver(context);
    if (bounds.IsRounded()) {
      context.ClipRoundedRect(bounds);
      ApplySpreadToShadowShape(inner_rounded_rect, -shadow.Spread());
    } else {
      context.Clip(bounds.Rect());
    }

    DrawLooperBuilder draw_looper_builder;
    draw_looper_builder.AddShadow(ToFloatSize(shadow.Location()), shadow.Blur(),
                                  shadow_color,
                                  DrawLooperBuilder::kShadowRespectsTransforms,
                                  DrawLooperBuilder::kShadowIgnoresAlpha);
    context.SetDrawLooper(draw_looper_builder.DetachDrawLooper());

    Color fill_color(shadow_color.Red(), shadow_color.Green(),
                     shadow_color.Blue());
    FloatRect outer_rect = AreaCastingShadowInHole(bounds.Rect(), shadow);
    context.FillRectWithRoundedHole(outer_rect, inner_rounded_rect, fill_color);
  }
}

bool BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(
    const Document& document,
    const ComputedStyle& style) {
  return document.Printing() &&
         style.PrintColorAdjust() == EPrintColorAdjust::kEconomy &&
         (!document.GetSettings() ||
          !document.GetSettings()->GetShouldPrintBackgrounds());
}

bool BoxPainterBase::CalculateFillLayerOcclusionCulling(
    FillLayerOcclusionOutputList& reversed_paint_list,
    const FillLayer& fill_layer) {
  bool is_non_associative = false;
  for (auto* current_layer = &fill_layer; current_layer;
       current_layer = current_layer->Next()) {
    reversed_paint_list.push_back(current_layer);
    // Stop traversal when an opaque layer is encountered.
    // FIXME : It would be possible for the following occlusion culling test to
    // be more aggressive on layers with no repeat by testing whether the image
    // covers the layout rect.  Testing that here would imply duplicating a lot
    // of calculations that are currently done in
    // LayoutBoxModelObject::paintFillLayer. A more efficient solution might be
    // to move the layer recursion into paintFillLayer, or to compute the layer
    // geometry here and pass it down.

    // TODO(trchen): Need to check compositing mode as well.
    if (current_layer->GetBlendMode() != BlendMode::kNormal)
      is_non_associative = true;

    // TODO(trchen): A fill layer cannot paint if the calculated tile size is
    // empty.  This occlusion check can be wrong.
    if (current_layer->ClipOccludesNextLayers() &&
        current_layer->ImageOccludesNextLayers(*document_, style_)) {
      if (current_layer->Clip() == EFillBox::kBorder)
        is_non_associative = false;
      break;
    }
  }
  return is_non_associative;
}

BoxPainterBase::FillLayerInfo::FillLayerInfo(
    const Document& doc,
    const ComputedStyle& style,
    bool is_scroll_container,
    Color bg_color,
    const FillLayer& layer,
    BackgroundBleedAvoidance bleed_avoidance,
    RespectImageOrientationEnum respect_image_orientation,
    PhysicalBoxSides sides_to_include,
    bool is_inline,
    bool is_painting_scrolling_background)
    : image(layer.GetImage()),
      color(bg_color),
      respect_image_orientation(respect_image_orientation),
      sides_to_include(sides_to_include),
      is_bottom_layer(!layer.Next()),
      is_border_fill(layer.Clip() == EFillBox::kBorder),
      is_clipped_with_local_scrolling(is_scroll_container &&
                                      layer.Attachment() ==
                                          EFillAttachment::kLocal) {
  // When printing backgrounds is disabled or using economy mode,
  // change existing background colors and images to a solid white background.
  // If there's no bg color or image, leave it untouched to avoid affecting
  // transparency.  We don't try to avoid loading the background images,
  // because this style flag is only set when printing, and at that point
  // we've already loaded the background images anyway. (To avoid loading the
  // background images we'd have to do this check when applying styles rather
  // than while layout.)
  if (BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(doc, style)) {
    // Note that we can't reuse this variable below because the bgColor might
    // be changed.
    bool should_paint_background_color = is_bottom_layer && color.Alpha();
    if (image || should_paint_background_color) {
      color = Color::kWhite;
      image = nullptr;
    }
  }

  // Background images are not allowed at the inline level in forced colors
  // mode when forced-color-adjust is auto. This ensures that the inline images
  // are not painted on top of the forced colors mode backplate.
  if (doc.InForcedColorsMode() && is_inline &&
      style.ForcedColorAdjust() != EForcedColorAdjust::kNone)
    image = nullptr;

  const bool has_rounded_border =
      style.HasBorderRadius() && !sides_to_include.IsEmpty();
  // BorderFillBox radius clipping is taken care of by
  // BackgroundBleedClip{Only,Layer}
  is_rounded_fill =
      has_rounded_border && !is_painting_scrolling_background &&
      !(is_border_fill && BleedAvoidanceIsClipping(bleed_avoidance));
  is_printing = doc.Printing();

  should_paint_image = image && image->CanRender();
  should_paint_color =
      is_bottom_layer && color.Alpha() &&
      (!should_paint_image || !layer.ImageOccludesNextLayers(doc, style));
  should_paint_color_with_paint_worklet_image =
      should_paint_color &&
      RuntimeEnabledFeatures::CompositeBGColorAnimationEnabled() &&
      style.HasCurrentBackgroundColorAnimation();
}

namespace {

// Given the |size| that the whole image should draw at, and the input phase
// requested by the content, and the space between repeated tiles, return a
// rectangle with |size| and a location that respects the phase but is no more
// than one size + space in magnitude. In practice, this means that if there is
// no repeating the returned rect would contain the destination_offset
// location. The destination_offset passed here must exactly match the location
// of the subset in a following call to ComputeSubsetForBackground.
FloatRect ComputePhaseForBackground(const FloatPoint& destination_offset,
                                    const FloatSize& size,
                                    const FloatPoint& phase,
                                    const FloatSize& spacing) {
  const FloatSize step_per_tile(size + spacing);
  return FloatRect(
      FloatPoint(
          destination_offset.X() + fmodf(-phase.X(), step_per_tile.Width()),
          destination_offset.Y() + fmodf(-phase.Y(), step_per_tile.Height())),
      size);
}

// Compute the image subset, in intrinsic image coordinates, that gets mapped
// onto the |subset|, when the whole image would be drawn with phase and size
// given by |phase_and_size|. Assumes |phase_and_size| contains |subset|. The
// location of the requested subset should be the painting snapped location, or
// whatever was used as a destination_offset in ComputePhaseForBackground.
//
// It is used to undo the offset added in ComputePhaseForBackground. The size
// of requested subset should be the unsnapped size so that the computed
// scale and location in the source image can be correctly determined.
FloatRect ComputeSubsetForBackground(const FloatRect& phase_and_size,
                                     const FloatRect& subset,
                                     const FloatSize& intrinsic_size) {
  // TODO(schenney): Re-enable this after determining why it fails for
  // CAP, and maybe other cases.
  // DCHECK(phase_and_size.Contains(subset));

  const FloatSize scale(phase_and_size.Width() / intrinsic_size.Width(),
                        phase_and_size.Height() / intrinsic_size.Height());
  return FloatRect((subset.X() - phase_and_size.X()) / scale.Width(),
                   (subset.Y() - phase_and_size.Y()) / scale.Height(),
                   subset.Width() / scale.Width(),
                   subset.Height() / scale.Height());
}

FloatRect SnapSourceRectIfNearIntegral(const FloatRect src_rect) {
  // Round to avoid filtering pulling in neighboring pixels, for the
  // common case of sprite maps, but only if we're close to an integral size.
  // "Close" in this context means we will allow floating point inaccuracy,
  // when converted to layout units, to be at most one LayoutUnit::Epsilon and
  // still snap.
  if (std::abs(std::round(src_rect.X()) - src_rect.X()) <=
          LayoutUnit::Epsilon() &&
      std::abs(std::round(src_rect.Y()) - src_rect.Y()) <=
          LayoutUnit::Epsilon() &&
      std::abs(std::round(src_rect.MaxX()) - src_rect.MaxX()) <=
          LayoutUnit::Epsilon() &&
      std::abs(std::round(src_rect.MaxY()) - src_rect.MaxY()) <=
          LayoutUnit::Epsilon()) {
    return FloatRect(RoundedIntRect(src_rect));
  }
  return src_rect;
}

// The unsnapped_subset_size should be the target painting area implied by the
//   content, without any snapping applied. It is necessary to correctly
//   compute the subset of the source image to paint into the destination.
// The snapped_paint_rect should be the target destination for painting into.
// The phase is never snapped.
// The tile_size is the total image size. The mapping from this size
//   to the unsnapped_dest_rect size defines the scaling of the image for
//   sprite computation.
void DrawTiledBackground(GraphicsContext& context,
                         Image* image,
                         const FloatSize& unsnapped_subset_size,
                         const FloatRect& snapped_paint_rect,
                         const FloatPoint& phase,
                         const FloatSize& tile_size,
                         SkBlendMode op,
                         const FloatSize& repeat_spacing,
                         bool has_filter_property,
                         RespectImageOrientationEnum respect_orientation) {
  DCHECK(!tile_size.IsEmpty());

  // Use the intrinsic size of the image if it has one, otherwise force the
  // generated image to be the tile size.
  FloatSize intrinsic_tile_size(image->Size());
  // image-resolution information is baked into the given parameters, but we
  // need oriented size. That requires explicitly applying orientation here.
  if (respect_orientation &&
      image->CurrentFrameOrientation().UsesWidthAsHeight()) {
    intrinsic_tile_size = intrinsic_tile_size.TransposedSize();
  }

  FloatSize scale(1, 1);
  if (!image->HasIntrinsicSize() ||
      // TODO(crbug.com/1042783): This is not checking for real empty image
      // (for which we have checked and skipped the whole FillLayer), but for
      // that a subpixel image size is rounded to empty, to avoid infinite tile
      // scale that would be calculated in the |else| part.
      // We should probably support subpixel size here.
      intrinsic_tile_size.IsEmpty()) {
    intrinsic_tile_size = tile_size;
  } else {
    scale = FloatSize(tile_size.Width() / intrinsic_tile_size.Width(),
                      tile_size.Height() / intrinsic_tile_size.Height());
  }

  const FloatRect one_tile_rect = ComputePhaseForBackground(
      snapped_paint_rect.Location(), tile_size, phase, repeat_spacing);

  // Check and see if a single draw of the image can cover the entire area we
  // are supposed to tile. The dest_rect_for_subset must use the same
  // location that was used in ComputePhaseForBackground and the unsnapped
  // destination rect in order to correctly evaluate the subset size and
  // location in the presence of border snapping and zoom.
  FloatRect dest_rect_for_subset(snapped_paint_rect.Location(),
                                 unsnapped_subset_size);
  if (one_tile_rect.Contains(dest_rect_for_subset)) {
    FloatRect visible_src_rect = ComputeSubsetForBackground(
        one_tile_rect, dest_rect_for_subset, intrinsic_tile_size);
    visible_src_rect = SnapSourceRectIfNearIntegral(visible_src_rect);

    // When respecting image orientation, the drawing code expects the source
    // rect to be in the unrotated image space, but we have computed it here in
    // the rotated space in order to position and size the background. Undo the
    // src rect rotation if necessary.
    if (respect_orientation && !image->HasDefaultOrientation()) {
      visible_src_rect = image->CorrectSrcRectForImageOrientation(
          intrinsic_tile_size, visible_src_rect);
    }

    context.DrawImage(image, Image::kSyncDecode, snapped_paint_rect,
                      &visible_src_rect, has_filter_property, op,
                      respect_orientation);
    return;
  }

  // At this point we have decided to tile the image to fill the dest rect.
  // Note that this tile rect uses the image's pre-scaled size.
  FloatRect tile_rect(FloatPoint(), intrinsic_tile_size);

  // Farther down the pipeline we will use the scaled tile size to determine
  // which dimensions to clamp or repeat in. We do not want to repeat when the
  // tile size rounds to match the dest in a given dimension, to avoid having
  // a single row or column repeated when the developer almost certainly
  // intended the image to not repeat (this generally occurs under zoom).
  //
  // So detect when we do not want to repeat and set the scale to round the
  // values in that dimension.
  if (fabs(tile_size.Width() - snapped_paint_rect.Width()) <= 0.5) {
    scale.SetWidth(snapped_paint_rect.Width() / intrinsic_tile_size.Width());
  }
  if (fabs(tile_size.Height() - snapped_paint_rect.Height()) <= 0.5) {
    scale.SetHeight(snapped_paint_rect.Height() / intrinsic_tile_size.Height());
  }

  // This call takes the unscaled image, applies the given scale, and paints
  // it into the snapped_dest_rect using phase from one_tile_rect and the
  // given repeat spacing. Note the phase is already scaled.
  context.DrawImageTiled(image, snapped_paint_rect, tile_rect, scale,
                         one_tile_rect.Location(), repeat_spacing, op,
                         respect_orientation);
}

// Returning false meaning that we need to fall back to the main thread for the
// background color animation.
bool GetBGColorPaintWorkletParams(const BoxPainterBase::FillLayerInfo& info,
                                  const Document* document,
                                  Node* node,
                                  Vector<Color>* animated_colors,
                                  Vector<double>* offsets) {
  if (!info.should_paint_color_with_paint_worklet_image)
    return false;
  BackgroundColorPaintImageGenerator* generator =
      document->GetFrame()->GetBackgroundColorPaintImageGenerator();
  return generator->GetBGColorPaintWorkletParams(node, animated_colors,
                                                 offsets);
}

void FillRectWithPaintWorklet(const Document* document,
                              const BoxPainterBase::FillLayerInfo& info,
                              Node* node,
                              const FloatRoundedRect& dest_rect,
                              GraphicsContext& context,
                              const Vector<Color>& animated_colors,
                              const Vector<double>& offsets) {
  FloatRect src_rect(FloatPoint(), dest_rect.Rect().Size());
  BackgroundColorPaintImageGenerator* generator =
      document->GetFrame()->GetBackgroundColorPaintImageGenerator();
  scoped_refptr<Image> paint_worklet_image =
      generator->Paint(src_rect.Size(), node, animated_colors, offsets);
  context.DrawImageRRect(
      paint_worklet_image.get(), Image::kSyncDecode, dest_rect, src_rect,
      node && node->ComputedStyleRef().HasFilterInducingProperty(),
      SkBlendMode::kSrcOver, info.respect_image_orientation);
}

inline bool PaintFastBottomLayer(const Document* document,
                                 Node* node,
                                 const PaintInfo& paint_info,
                                 const BoxPainterBase::FillLayerInfo& info,
                                 const PhysicalRect& rect,
                                 const FloatRoundedRect& border_rect,
                                 BackgroundImageGeometry& geometry,
                                 Image* image,
                                 SkBlendMode composite_op) {
  // Painting a background image from an ancestor onto a cell is a complex case.
  if (geometry.CellUsingContainerBackground())
    return false;
  // Complex cases not handled on the fast path.
  if (!info.is_bottom_layer || !info.is_border_fill)
    return false;

  // Transparent layer, nothing to paint.
  if (!info.should_paint_color && !info.should_paint_image)
    return true;

  // Compute the destination rect for painting the color here because we may
  // need it for computing the image painting rect for optimization.
  GraphicsContext& context = paint_info.context;
  FloatRoundedRect color_border =
      info.is_rounded_fill ? border_rect
                           : FloatRoundedRect(PixelSnappedIntRect(rect));
  // When the layer has an image, figure out whether it is covered by a single
  // tile. The border for painting images may not be the same as the color due
  // to optimizations for the image painting destination that avoid painting
  // under the border.
  FloatRect image_tile;
  FloatRoundedRect image_border;
  if (info.should_paint_image) {
    // Avoid image shaders when printing (poorly supported in PDF).
    if (info.is_rounded_fill && info.is_printing)
      return false;

    // Compute the dest rect we will be using for images.
    image_border =
        info.is_rounded_fill
            ? color_border
            : FloatRoundedRect(FloatRect(geometry.SnappedDestRect()));

    if (!image_border.Rect().IsEmpty()) {
      // We cannot optimize if the tile is too small.
      if (geometry.TileSize().width < image_border.Rect().Width() ||
          geometry.TileSize().height < image_border.Rect().Height())
        return false;

      // Phase calculation uses the actual painted location, given by the
      // border-snapped destination rect.
      image_tile = ComputePhaseForBackground(
          FloatPoint(geometry.SnappedDestRect().offset),
          FloatSize(geometry.TileSize()), geometry.Phase(),
          FloatSize(geometry.SpaceSize()));

      // Force the image tile to LayoutUnit precision, which is the precision
      // it was calculated in. This avoids bleeding due to values very close to
      // integers.
      // The test images/sprite-no-bleed.html fails on two of the sub-cases
      // due to this rounding still not being enough to make the Contains check
      // pass. The best way to fix this would be to remove the paint rect offset
      // from the tile computation, because we effectively add it in
      // ComputePhaseForBackground then remove it in ComputeSubsetForBackground.
      image_tile =
          FloatRect(PhysicalRect::FastAndLossyFromFloatRect(image_tile));
      // We cannot optimize if the tile is misaligned.
      if (!image_tile.Contains(image_border.Rect()))
        return false;
    }
  }

  // At this point we're committed to the fast path: the destination (r)rect
  // fits within a single tile, and we can paint it using direct draw(R)Rect()
  // calls.
  base::Optional<RoundedInnerRectClipper> clipper;
  if (info.is_rounded_fill && !color_border.IsRenderable()) {
    // When the rrect is not renderable, we resort to clipping.
    // RoundedInnerRectClipper handles this case via discrete, corner-wise
    // clipping.
    clipper.emplace(context, rect, color_border);
    color_border.SetRadii(FloatRoundedRect::Radii());
    image_border.SetRadii(FloatRoundedRect::Radii());
  }

  // Paint the color if needed.
  if (info.should_paint_color) {
    Vector<Color> animated_colors;
    Vector<double> offsets;
    if (GetBGColorPaintWorkletParams(info, document, node, &animated_colors,
                                     &offsets)) {
      FillRectWithPaintWorklet(document, info, node, color_border, context,
                               animated_colors, offsets);
    } else {
      context.FillRoundedRect(color_border, info.color);
    }
  }

  // Paint the image if needed.
  if (!info.should_paint_image || !image || image_tile.IsEmpty())
    return true;

  // Generated images will be created at the desired tile size, so assume their
  // intrinsic size is the requested tile size.
  bool has_intrinsic_size = image->HasIntrinsicSize();
  const FloatSize intrinsic_tile_size =
      !has_intrinsic_size
          ? image_tile.Size()
          : FloatSize(image->Size(info.respect_image_orientation));

  // Subset computation needs the same location as was used with
  // ComputePhaseForBackground above, but needs the unsnapped destination
  // size to correctly calculate sprite subsets in the presence of zoom. But if
  // this is a generated image sized according to the tile size (which is a
  // snapped value), use the snapped dest rect instead.
  FloatRect dest_rect_for_subset(
      FloatPoint(geometry.SnappedDestRect().offset),
      !has_intrinsic_size ? FloatSize(geometry.SnappedDestRect().size)
                          : FloatSize(geometry.UnsnappedDestRect().size));
  // Content providers almost always choose source pixels at integer locations,
  // so snap to integers. This is particuarly important for sprite maps.
  // Calculation up to this point, in LayoutUnits, can lead to small variations
  // from integer size, so it is safe to round without introducing major issues.
  const FloatRect unrounded_subset = ComputeSubsetForBackground(
      image_tile, dest_rect_for_subset, intrinsic_tile_size);
  FloatRect src_rect = SnapSourceRectIfNearIntegral(unrounded_subset);

  // If we have snapped the image size to 0, revert the rounding.
  if (src_rect.IsEmpty())
    src_rect = unrounded_subset;

  // When respecting image orientation, the drawing code expects the source rect
  // to be in the unrotated image space, but we have computed it here in the
  // rotated space in order to position and size the background. Undo the src
  // rect rotation if necessaary.
  if (info.respect_image_orientation && !image->HasDefaultOrientation()) {
    src_rect =
        image->CorrectSrcRectForImageOrientation(intrinsic_tile_size, src_rect);
  }

  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
               "data",
               inspector_paint_image_event::Data(
                   node, *info.image, FloatRect(image->Rect()),
                   FloatRect(image_border.Rect())));

  // Since there is no way for the developer to specify decode behavior, use
  // kSync by default.
  context.DrawImageRRect(
      image, Image::kSyncDecode, image_border, src_rect,
      node && node->ComputedStyleRef().HasFilterInducingProperty(),
      composite_op, info.respect_image_orientation);

  if (node && info.image && info.image->IsImageResource()) {
    PaintTimingDetector::NotifyBackgroundImagePaint(
        *node, *image, To<StyleFetchedImage>(*info.image),
        paint_info.context.GetPaintController().CurrentPaintChunkProperties(),
        RoundedIntRect(image_border.Rect()));

    LocalDOMWindow* window = node->GetDocument().domWindow();
    DCHECK(window);
    ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
        *node, To<StyleFetchedImage>(*info.image),
        context.GetPaintController().CurrentPaintChunkProperties(),
        RoundedIntRect(image_border.Rect()));
  }
  return true;
}

// Inset the background rect by a "safe" amount: 1/2 border-width for opaque
// border styles, 1/6 border-width for double borders.
FloatRoundedRect BackgroundRoundedRectAdjustedForBleedAvoidance(
    const ComputedStyle& style,
    const PhysicalRect& border_rect,
    bool object_has_multiple_boxes,
    PhysicalBoxSides sides_to_include,
    FloatRoundedRect background_rounded_rect) {
  // TODO(fmalita): we should be able to fold these parameters into
  // BoxBorderInfo or BoxDecorationData and avoid calling getBorderEdgeInfo
  // redundantly here.
  BorderEdge edges[4];
  style.GetBorderEdgeInfo(edges, sides_to_include);

  // Use the most conservative inset to avoid mixed-style corner issues.
  float fractional_inset = 1.0f / 2;
  for (auto& edge : edges) {
    if (edge.BorderStyle() == EBorderStyle::kDouble) {
      fractional_inset = 1.0f / 6;
      break;
    }
  }

  FloatRectOutsets insets(
      -fractional_inset *
          edges[static_cast<unsigned>(BoxSide::kTop)].UsedWidth(),
      -fractional_inset *
          edges[static_cast<unsigned>(BoxSide::kRight)].UsedWidth(),
      -fractional_inset *
          edges[static_cast<unsigned>(BoxSide::kBottom)].UsedWidth(),
      -fractional_inset *
          edges[static_cast<unsigned>(BoxSide::kLeft)].UsedWidth());

  FloatRect inset_rect(background_rounded_rect.Rect());
  inset_rect.Expand(insets);
  FloatRoundedRect::Radii inset_radii(background_rounded_rect.GetRadii());
  inset_radii.Shrink(-insets.Top(), -insets.Bottom(), -insets.Left(),
                     -insets.Right());
  return FloatRoundedRect(inset_rect, inset_radii);
}

FloatRoundedRect RoundedBorderRectForClip(
    const ComputedStyle& style,
    const BoxPainterBase::FillLayerInfo& info,
    const FillLayer& bg_layer,
    const PhysicalRect& rect,
    bool object_has_multiple_boxes,
    const PhysicalSize& flow_box_size,
    BackgroundBleedAvoidance bleed_avoidance,
    LayoutRectOutsets border_padding_insets) {
  if (!info.is_rounded_fill)
    return FloatRoundedRect();

  FloatRoundedRect border = RoundedBorderGeometry::PixelSnappedRoundedBorder(
      style, rect, info.sides_to_include);
  if (object_has_multiple_boxes) {
    FloatRoundedRect segment_border =
        RoundedBorderGeometry::PixelSnappedRoundedBorder(
            style,
            PhysicalRect(PhysicalOffset(),
                         PhysicalSize(FlooredIntSize(flow_box_size))),
            info.sides_to_include);
    border.SetRadii(segment_border.GetRadii());
  }

  if (info.is_border_fill &&
      bleed_avoidance == kBackgroundBleedShrinkBackground) {
    border = BackgroundRoundedRectAdjustedForBleedAvoidance(
        style, rect, object_has_multiple_boxes, info.sides_to_include, border);
  }

  // Clip to the padding or content boxes as necessary.
  // Use FastAndLossyFromFloatRect because we know it has been pixel snapped.
  PhysicalRect border_rect =
      PhysicalRect::FastAndLossyFromFloatRect(border.Rect());
  if (bg_layer.Clip() == EFillBox::kContent) {
    border = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
        style, border_rect, border_padding_insets, info.sides_to_include);
  } else if (bg_layer.Clip() == EFillBox::kPadding) {
    border = RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
        style, border_rect, info.sides_to_include);
  }
  return border;
}

void PaintFillLayerBackground(const Document* document,
                              GraphicsContext& context,
                              const BoxPainterBase::FillLayerInfo& info,
                              Node* node,
                              Image* image,
                              SkBlendMode composite_op,
                              const BackgroundImageGeometry& geometry,
                              const PhysicalRect& scrolled_paint_rect) {
  // Paint the color first underneath all images, culled if background image
  // occludes it.
  // TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the
  // culling test by verifying whether the background image covers the entire
  // painting area.
  if (info.is_bottom_layer && info.color.Alpha() && info.should_paint_color) {
    IntRect background_rect(PixelSnappedIntRect(scrolled_paint_rect));
    Vector<Color> animated_colors;
    Vector<double> offsets;
    if (GetBGColorPaintWorkletParams(info, document, node, &animated_colors,
                                     &offsets)) {
      FillRectWithPaintWorklet(document, info, node,
                               FloatRoundedRect(background_rect), context,
                               animated_colors, offsets);
    } else {
      context.FillRect(background_rect, info.color);
    }
  }

  // No progressive loading of the background image.
  // NOTE: This method can be called with no image in situations when a bad
  // resource locator is given such as "//:0", so still check for image.
  if (info.should_paint_image && !geometry.SnappedDestRect().IsEmpty() &&
      !geometry.TileSize().IsEmpty() && image) {
    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
                 "data",
                 inspector_paint_image_event::Data(
                     node, *info.image, FloatRect(image->Rect()),
                     FloatRect(scrolled_paint_rect)));
    DrawTiledBackground(
        context, image, FloatSize(geometry.UnsnappedDestRect().size),
        FloatRect(geometry.SnappedDestRect()), geometry.Phase(),
        FloatSize(geometry.TileSize()), composite_op,
        FloatSize(geometry.SpaceSize()),
        node && node->ComputedStyleRef().HasFilterInducingProperty(),
        info.respect_image_orientation);
    if (node && info.image && info.image->IsImageResource()) {
      PaintTimingDetector::NotifyBackgroundImagePaint(
          *node, *image, To<StyleFetchedImage>(*info.image),
          context.GetPaintController().CurrentPaintChunkProperties(),
          EnclosingIntRect(geometry.SnappedDestRect()));

      LocalDOMWindow* window = node->GetDocument().domWindow();
      DCHECK(window);
      ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
          *node, To<StyleFetchedImage>(*info.image),
          context.GetPaintController().CurrentPaintChunkProperties(),
          EnclosingIntRect(geometry.SnappedDestRect()));
    }
  }
}

LayoutRectOutsets AdjustOutsetsForEdgeInclusion(
    const LayoutRectOutsets outsets,
    const BoxPainterBase::FillLayerInfo& info) {
  LayoutRectOutsets adjusted = outsets;
  if (!info.sides_to_include.top)
    adjusted.SetTop(LayoutUnit());
  if (!info.sides_to_include.right)
    adjusted.SetRight(LayoutUnit());
  if (!info.sides_to_include.bottom)
    adjusted.SetBottom(LayoutUnit());
  if (!info.sides_to_include.left)
    adjusted.SetLeft(LayoutUnit());
  return adjusted;
}

bool ShouldApplyBlendOperation(const BoxPainterBase::FillLayerInfo& info,
                               const FillLayer& layer) {
  // For a mask layer, don't use the operator if this is the bottom layer.
  return !info.is_bottom_layer || layer.GetType() != EFillLayerType::kMask;
}

}  // anonymous namespace

LayoutRectOutsets BoxPainterBase::AdjustedBorderOutsets(
    const FillLayerInfo& info) const {
  return AdjustOutsetsForEdgeInclusion(ComputeBorders(), info);
}

void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
                                    const Color& color,
                                    const FillLayer& bg_layer,
                                    const PhysicalRect& rect,
                                    BackgroundBleedAvoidance bleed_avoidance,
                                    BackgroundImageGeometry& geometry,
                                    bool object_has_multiple_boxes,
                                    const PhysicalSize& flow_box_size) {
  GraphicsContext& context = paint_info.context;
  if (rect.IsEmpty())
    return;

  const FillLayerInfo info =
      GetFillLayerInfo(color, bg_layer, bleed_avoidance,
                       IsPaintingScrollingBackground(paint_info));
  // If we're not actually going to paint anything, abort early.
  if (!info.should_paint_image && !info.should_paint_color)
    return;

  GraphicsContextStateSaver clip_with_scrolling_state_saver(
      context, info.is_clipped_with_local_scrolling);
  auto scrolled_paint_rect =
      AdjustRectForScrolledContent(paint_info, info, rect);
  const auto did_adjust_paint_rect = scrolled_paint_rect != rect;

  scoped_refptr<Image> image;
  SkBlendMode composite_op = SkBlendMode::kSrcOver;
  base::Optional<ScopedInterpolationQuality> interpolation_quality_context;
  if (info.should_paint_image) {
    geometry.Calculate(paint_info.PaintContainer(), paint_info.phase,
                       paint_info.GetGlobalPaintFlags(), bg_layer,
                       scrolled_paint_rect);
    image = info.image->GetImage(
        geometry.ImageClient(), geometry.ImageDocument(), geometry.ImageStyle(),
        FloatSize(geometry.TileSize()));
    interpolation_quality_context.emplace(context,
                                          geometry.ImageInterpolationQuality());

    if (ShouldApplyBlendOperation(info, bg_layer)) {
      composite_op = WebCoreCompositeToSkiaComposite(bg_layer.Composite(),
                                                     bg_layer.GetBlendMode());
    }
  }

  LayoutRectOutsets border = ComputeBorders();
  LayoutRectOutsets padding = ComputePadding();
  LayoutRectOutsets border_padding_insets = -(border + padding);
  FloatRoundedRect border_rect = RoundedBorderRectForClip(
      style_, info, bg_layer, rect, object_has_multiple_boxes, flow_box_size,
      bleed_avoidance, border_padding_insets);

  // Fast path for drawing simple color backgrounds. Do not use the fast
  // path with images if the dest rect has been adjusted for scrolling
  // backgrounds because correcting the dest rect for scrolling reduces the
  // accuracy of the destination rects. Also disable the fast path for images
  // if we are shrinking the background for bleed avoidance, because this
  // adjusts the border rects in a way that breaks the optimization.
  bool disable_fast_path =
      info.should_paint_image &&
      (bleed_avoidance == kBackgroundBleedShrinkBackground ||
       did_adjust_paint_rect);
  if (!disable_fast_path &&
      PaintFastBottomLayer(document_, node_, paint_info, info, rect,
                           border_rect, geometry, image.get(), composite_op)) {
    return;
  }

  base::Optional<RoundedInnerRectClipper> clip_to_border;
  if (info.is_rounded_fill)
    clip_to_border.emplace(context, rect, border_rect);

  if (bg_layer.Clip() == EFillBox::kText) {
    PaintFillLayerTextFillBox(context, info, image.get(), composite_op,
                              geometry, rect, scrolled_paint_rect,
                              object_has_multiple_boxes);
    return;
  }

  GraphicsContextStateSaver background_clip_state_saver(context, false);
  switch (bg_layer.Clip()) {
    case EFillBox::kPadding:
    case EFillBox::kContent: {
      if (info.is_rounded_fill)
        break;

      // Clip to the padding or content boxes as necessary.
      PhysicalRect clip_rect = scrolled_paint_rect;
      clip_rect.Contract(AdjustOutsetsForEdgeInclusion(border, info));
      if (bg_layer.Clip() == EFillBox::kContent)
        clip_rect.Contract(AdjustOutsetsForEdgeInclusion(padding, info));
      background_clip_state_saver.Save();
      // TODO(chrishtr): this should be pixel-snapped.
      context.Clip(FloatRect(clip_rect));
      break;
    }
    case EFillBox::kBorder:
      break;
    case EFillBox::kText:  // fall through
    default:
      NOTREACHED();
      break;
  }

  PaintFillLayerBackground(document_, context, info, node_, image.get(),
                           composite_op, geometry, scrolled_paint_rect);
}

void BoxPainterBase::PaintFillLayerTextFillBox(
    GraphicsContext& context,
    const BoxPainterBase::FillLayerInfo& info,
    Image* image,
    SkBlendMode composite_op,
    const BackgroundImageGeometry& geometry,
    const PhysicalRect& rect,
    const PhysicalRect& scrolled_paint_rect,
    bool object_has_multiple_boxes) {
  // First figure out how big the mask has to be. It should be no bigger
  // than what we need to actually render, so we should intersect the dirty
  // rect with the border box of the background.
  IntRect mask_rect = PixelSnappedIntRect(rect);

  // We draw the background into a separate layer, to be later masked with
  // yet another layer holding the text content.
  GraphicsContextStateSaver background_clip_state_saver(context, false);
  background_clip_state_saver.Save();
  context.Clip(mask_rect);
  context.BeginLayer(1, composite_op);

  PaintFillLayerBackground(document_, context, info, node_, image,
                           SkBlendMode::kSrcOver, geometry,
                           scrolled_paint_rect);

  // Create the text mask layer and draw the text into the mask. We do this by
  // painting using a special paint phase that signals to InlineTextBoxes that
  // they should just add their contents to the clip.
  context.BeginLayer(1, SkBlendMode::kDstIn);

  PaintTextClipMask(context, mask_rect, scrolled_paint_rect.offset,
                    object_has_multiple_boxes);

  context.EndLayer();  // Text mask layer.
  context.EndLayer();  // Background layer.
}

void BoxPainterBase::PaintBorder(const ImageResourceObserver& obj,
                                 const Document& document,
                                 Node* node,
                                 const PaintInfo& info,
                                 const PhysicalRect& rect,
                                 const ComputedStyle& style,
                                 BackgroundBleedAvoidance bleed_avoidance,
                                 PhysicalBoxSides sides_to_include) {
  // border-image is not affected by border-radius.
  if (NinePieceImagePainter::Paint(info.context, obj, document, node, rect,
                                   style, style.BorderImage())) {
    return;
  }

  const BoxBorderPainter border_painter(rect, style, bleed_avoidance,
                                        sides_to_include);
  border_painter.PaintBorder(info, rect);
}

void BoxPainterBase::PaintMaskImages(const PaintInfo& paint_info,
                                     const PhysicalRect& paint_rect,
                                     const ImageResourceObserver& obj,
                                     BackgroundImageGeometry& geometry,
                                     PhysicalBoxSides sides_to_include) {
  if (!style_.HasMask() || style_.Visibility() != EVisibility::kVisible)
    return;

  PaintFillLayers(paint_info, Color::kTransparent, style_.MaskLayers(),
                  paint_rect, geometry);
  NinePieceImagePainter::Paint(paint_info.context, obj, *document_, node_,
                               paint_rect, style_, style_.MaskBoxImage(),
                               sides_to_include);
}

bool BoxPainterBase::ShouldSkipPaintUnderInvalidationChecking(
    const LayoutBox& box) {
  DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());

  // Disable paint under-invalidation checking for cases that under-invalidation
  // is intensional and/or harmless.

  // A box having delayed-invalidation may change before it's actually
  // invalidated. Note that we still report harmless under-invalidation of
  // non-delayed-invalidation animated background, which should be ignored.
  if (box.ShouldDelayFullPaintInvalidation())
    return true;

  // We always paint a MediaSliderPart using the latest data (buffered ranges,
  // current time and duration) which may be different from the cached data.
  if (box.StyleRef().EffectiveAppearance() == kMediaSliderPart)
    return true;

  // We paint an indeterminate progress based on the position calculated from
  // the animation progress. Harmless under-invalidatoin may happen during a
  // paint that is not scheduled for animation.
  if (box.IsProgress() && !To<LayoutProgress>(box).IsDeterminate())
    return true;

  return false;
}

}  // namespace blink
