// 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/background_image_geometry.h"

#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_table_col.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"

namespace blink {

namespace {

// Return the amount of space to leave between image tiles for the
// background-repeat: space property.
inline LayoutUnit GetSpaceBetweenImageTiles(LayoutUnit area_size,
                                            LayoutUnit tile_size) {
  int number_of_tiles = (area_size / tile_size).ToInt();
  LayoutUnit space(-1);
  if (number_of_tiles > 1) {
    // Spec doesn't specify rounding, so use the same method as for
    // background-repeat: round.
    space = (area_size - number_of_tiles * tile_size) / (number_of_tiles - 1);
  }

  return space;
}

bool FixedBackgroundPaintsInLocalCoordinates(
    const LayoutObject& obj,
    const GlobalPaintFlags global_paint_flags) {
  if (!obj.IsLayoutView())
    return false;

  const LayoutView& view = ToLayoutView(obj);

  // TODO(wangxianzhu): For CAP, inline this function into
  // FixedBackgroundPaintsInLocalCoordinates().
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
    return view.GetBackgroundPaintLocation() !=
           kBackgroundPaintInScrollingContents;
  }

  if (global_paint_flags & kGlobalPaintFlattenCompositingLayers)
    return false;

  PaintLayer* root_layer = view.Layer();
  if (!root_layer || root_layer->GetCompositingState() == kNotComposited)
    return false;

  CompositedLayerMapping* mapping = root_layer->GetCompositedLayerMapping();
  return !mapping->BackgroundPaintsOntoScrollingContentsLayer();
}

IntPoint AccumulatedScrollOffsetForFixedBackground(
    const LayoutBoxModelObject& object,
    const LayoutBoxModelObject* container) {
  IntPoint result;
  if (&object == container)
    return result;

  LayoutObject::AncestorSkipInfo skip_info(container);
  for (const LayoutBlock* block = object.ContainingBlock(&skip_info);
       block && !skip_info.AncestorSkipped();
       block = block->ContainingBlock(&skip_info)) {
    if (block->HasOverflowClip())
      result += block->ScrolledContentOffset();
    if (block == container)
      break;
  }
  return result;
}

}  // anonymous namespace

bool NeedsFullSizeDestination(const FillLayer& fill_layer) {
  // When dealing with a mask, the dest rect needs to maintain the full size
  // and the mask should be expanded to fill it out. This allows the mask to
  // correctly mask the entire area it is meant to. This is unnecessary on the
  // last layer, so the normal background path is taken for efficiency when
  // creating the paint shader later on.
  return fill_layer.GetType() == EFillLayerType::kMask && fill_layer.Next() &&
         fill_layer.Composite() != kCompositeSourceOver;
}

void BackgroundImageGeometry::SetNoRepeatX(const FillLayer& fill_layer,
                                           LayoutUnit x_offset,
                                           LayoutUnit snapped_x_offset) {
  if (NeedsFullSizeDestination(fill_layer)) {
    SetPhaseX(-x_offset.ToFloat());
    SetSpaceSize(
        LayoutSize(unsnapped_dest_rect_.Width(), SpaceSize().Height()));
    return;
  }

  // The snapped offset may not yet be snapped, so make sure it is an integer.
  snapped_x_offset = LayoutUnit(RoundToInt(snapped_x_offset));

  if (x_offset > 0) {
    DCHECK(snapped_x_offset >= LayoutUnit());
    // Move the dest rect if the offset is positive. The image "stays" where
    // it is over the dest rect, so this effectively modifies the phase.
    unsnapped_dest_rect_.Move(x_offset, LayoutUnit());
    snapped_dest_rect_.Move(snapped_x_offset, LayoutUnit());

    // Make the dest as wide as a tile, which will reduce the dest
    // rect if the tile is too small to fill the paint_rect. If not,
    // the dest rect will be clipped when intersected with the paint
    // rect.
    unsnapped_dest_rect_.SetWidth(tile_size_.Width());
    snapped_dest_rect_.SetWidth(tile_size_.Width());

    SetPhaseX(0);
  } else {
    // Otherwise, if the offset is negative use it to move the image under
    // the dest rect (since we can't paint outside the paint_rect).
    SetPhaseX(-x_offset.ToFloat());

    // Reduce the width of the dest rect to draw only the portion of the
    // tile that remains visible after offsetting the image.
    // TODO(schenney): This might grow the dest rect if the dest rect has
    // been adjusted for opaque borders.
    unsnapped_dest_rect_.SetWidth(tile_size_.Width() + x_offset);
    snapped_dest_rect_.SetWidth(tile_size_.Width() + snapped_x_offset);
  }

  // Force the horizontal space to zero, retaining vertical.
  SetSpaceSize(LayoutSize(LayoutUnit(), SpaceSize().Height()));
}

void BackgroundImageGeometry::SetNoRepeatY(const FillLayer& fill_layer,
                                           LayoutUnit y_offset,
                                           LayoutUnit snapped_y_offset) {
  if (NeedsFullSizeDestination(fill_layer)) {
    SetPhaseY(-y_offset.ToFloat());
    SetSpaceSize(
        LayoutSize(SpaceSize().Width(), unsnapped_dest_rect_.Height()));
    return;
  }

  // The snapped offset may not yet be snapped, so make sure it is an integer.
  snapped_y_offset = LayoutUnit(RoundToInt(snapped_y_offset));

  if (y_offset > 0) {
    DCHECK(snapped_y_offset >= LayoutUnit());
    // Move the dest rect if the offset is positive. The image "stays" where
    // it is in the paint rect, so this effectively modifies the phase.
    unsnapped_dest_rect_.Move(LayoutUnit(), y_offset);
    snapped_dest_rect_.Move(LayoutUnit(), snapped_y_offset);

    // Make the dest as wide as a tile, which will reduce the dest
    // rect if the tile is too small to fill the paint_rect. If not,
    // the dest rect will be clipped when intersected with the paint
    // rect.
    unsnapped_dest_rect_.SetHeight(tile_size_.Height());
    snapped_dest_rect_.SetHeight(tile_size_.Height());

    SetPhaseY(0);
  } else {
    // Otherwise, if the offset is negative, use it to move the image under
    // the dest rect (since we can't paint outside the paint_rect).
    SetPhaseY(-y_offset.ToFloat());

    // Reduce the height of the dest rect to draw only the portion of the
    // tile that remains visible after offsetting the image.
    // TODO(schenney): This might grow the dest rect if the dest rect has
    // been adjusted for opaque borders.
    unsnapped_dest_rect_.SetHeight(tile_size_.Height() + y_offset);
    snapped_dest_rect_.SetHeight(tile_size_.Height() + snapped_y_offset);
  }

  // Force the vertical space to zero, retaining horizontal.
  SetSpaceSize(LayoutSize(SpaceSize().Width(), LayoutUnit()));
}

void BackgroundImageGeometry::SetRepeatX(const FillLayer& fill_layer,
                                         LayoutUnit available_width,
                                         LayoutUnit extra_offset) {
  // All values are unsnapped to accurately set phase in the presence of
  // zoom and large values. That is, accurately render the
  // background-position value.
  if (tile_size_.Width()) {
    // Recompute computed_position because here we need to resolve against
    // unsnapped widths to correctly set the phase.
    LayoutUnit computed_position =
        MinimumValueForLength(fill_layer.PositionX(), available_width) -
        offset_in_background_.X();

    // Identify the number of tiles that fit within the computed
    // position in the direction we should be moving.
    float number_of_tiles_in_position;
    if (fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight) {
      number_of_tiles_in_position =
          (available_width - computed_position + extra_offset).ToFloat() /
          tile_size_.Width().ToFloat();
    } else {
      number_of_tiles_in_position =
          (computed_position + extra_offset).ToFloat() /
          tile_size_.Width().ToFloat();
    }
    // Assuming a non-integral number of tiles, find out how much of the
    // partial tile is visible. That is the phase.
    float fractional_position_within_tile =
        1.0f -
        (number_of_tiles_in_position - truncf(number_of_tiles_in_position));
    SetPhaseX(fractional_position_within_tile * tile_size_.Width());
  } else {
    SetPhaseX(0);
  }
  SetSpaceSize(LayoutSize(LayoutUnit(), SpaceSize().Height()));
}

void BackgroundImageGeometry::SetRepeatY(const FillLayer& fill_layer,
                                         LayoutUnit available_height,
                                         LayoutUnit extra_offset) {
  // All values are unsnapped to accurately set phase in the presence of
  // zoom and large values. That is, accurately render the
  // background-position value.
  if (tile_size_.Height()) {
    // Recompute computed_position because here we need to resolve against
    // unsnapped widths to correctly set the phase.
    LayoutUnit computed_position =
        MinimumValueForLength(fill_layer.PositionY(), available_height) -
        offset_in_background_.Y();

    // Identify the number of tiles that fit within the computed
    // position in the direction we should be moving.
    float number_of_tiles_in_position;
    if (fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom) {
      number_of_tiles_in_position =
          (available_height - computed_position + extra_offset).ToFloat() /
          tile_size_.Height().ToFloat();
    } else {
      number_of_tiles_in_position =
          (computed_position + extra_offset).ToFloat() /
          tile_size_.Height().ToFloat();
    }
    // Assuming a non-integral number of tiles, find out how much of the
    // partial tile is visible. That is the phase.
    float fractional_position_within_tile =
        1.0f -
        (number_of_tiles_in_position - truncf(number_of_tiles_in_position));
    SetPhaseY(fractional_position_within_tile * tile_size_.Height());
  } else {
    SetPhaseY(0);
  }
  SetSpaceSize(LayoutSize(SpaceSize().Width(), LayoutUnit()));
}

void BackgroundImageGeometry::SetSpaceX(LayoutUnit space,
                                        LayoutUnit extra_offset) {
  SetSpaceSize(LayoutSize(space, SpaceSize().Height()));
  // Modify the phase to start a full tile at the edge of the paint area
  LayoutUnit actual_width = tile_size_.Width() + space;
  SetPhaseX(actual_width ? actual_width - fmodf(extra_offset, actual_width)
                         : 0);
}

void BackgroundImageGeometry::SetSpaceY(LayoutUnit space,
                                        LayoutUnit extra_offset) {
  SetSpaceSize(LayoutSize(SpaceSize().Width(), space));
  // Modify the phase to start a full tile at the edge of the paint area
  LayoutUnit actual_height = tile_size_.Height() + space;
  SetPhaseY(actual_height ? actual_height - fmodf(extra_offset, actual_height)
                          : 0);
}

void BackgroundImageGeometry::UseFixedAttachment(
    const LayoutPoint& attachment_point) {
  LayoutPoint aligned_point = attachment_point;
  phase_.Move(
      std::max((aligned_point.X() - unsnapped_dest_rect_.X()).ToFloat(), 0.f),
      std::max((aligned_point.Y() - unsnapped_dest_rect_.Y()).ToFloat(), 0.f));
}

enum ColumnGroupDirection { kColumnGroupStart, kColumnGroupEnd };

static void ExpandToTableColumnGroup(const LayoutTableCell& cell,
                                     const LayoutTableCol& column_group,
                                     LayoutUnit& value,
                                     ColumnGroupDirection column_direction) {
  auto sibling_cell = column_direction == kColumnGroupStart
                          ? &LayoutTableCell::PreviousCell
                          : &LayoutTableCell::NextCell;
  for (const auto* sibling = (cell.*sibling_cell)(); sibling;
       sibling = (sibling->*sibling_cell)()) {
    LayoutTableCol* innermost_col =
        cell.Table()
            ->ColElementAtAbsoluteColumn(sibling->AbsoluteColumnIndex())
            .InnermostColOrColGroup();
    if (!innermost_col || innermost_col->EnclosingColumnGroup() != column_group)
      break;
    value += sibling->Size().Width();
  }
}

LayoutPoint BackgroundImageGeometry::GetOffsetForCell(
    const LayoutTableCell& cell,
    const LayoutBox& positioning_box) {
  LayoutSize border_spacing = LayoutSize(cell.Table()->HBorderSpacing(),
                                         cell.Table()->VBorderSpacing());
  if (positioning_box.IsTableSection())
    return cell.Location() - border_spacing;
  if (positioning_box.IsTableRow()) {
    return LayoutPoint(cell.Location().X(), LayoutUnit()) -
           LayoutSize(border_spacing.Width(), LayoutUnit());
  }

  LayoutRect sections_rect(LayoutPoint(), cell.Table()->Size());
  cell.Table()->SubtractCaptionRect(sections_rect);
  LayoutUnit height_of_captions =
      cell.Table()->Size().Height() - sections_rect.Height();
  LayoutPoint offset_in_background = LayoutPoint(
      LayoutUnit(), (cell.Section()->Location().Y() -
                     cell.Table()->BorderBefore() - height_of_captions) +
                        cell.Location().Y());

  DCHECK(positioning_box.IsLayoutTableCol());
  if (ToLayoutTableCol(positioning_box).IsTableColumn()) {
    return offset_in_background -
           LayoutSize(LayoutUnit(), border_spacing.Height());
  }

  DCHECK(ToLayoutTableCol(positioning_box).IsTableColumnGroup());
  LayoutUnit offset = offset_in_background.X();
  ExpandToTableColumnGroup(cell, ToLayoutTableCol(positioning_box), offset,
                           kColumnGroupStart);
  offset_in_background.Move(offset, LayoutUnit());
  return offset_in_background -
         LayoutSize(LayoutUnit(), border_spacing.Height());
}

LayoutSize BackgroundImageGeometry::GetBackgroundObjectDimensions(
    const LayoutTableCell& cell,
    const LayoutBox& positioning_box) {
  LayoutSize border_spacing = LayoutSize(cell.Table()->HBorderSpacing(),
                                         cell.Table()->VBorderSpacing());
  if (positioning_box.IsTableSection())
    return positioning_box.Size() - border_spacing - border_spacing;

  if (positioning_box.IsTableRow()) {
    return positioning_box.Size() -
           LayoutSize(border_spacing.Width(), LayoutUnit()) -
           LayoutSize(border_spacing.Width(), LayoutUnit());
  }

  DCHECK(positioning_box.IsLayoutTableCol());
  LayoutRect sections_rect(LayoutPoint(), cell.Table()->Size());
  cell.Table()->SubtractCaptionRect(sections_rect);
  LayoutUnit column_height = sections_rect.Height() -
                             cell.Table()->BorderBefore() -
                             border_spacing.Height() - border_spacing.Height();
  if (ToLayoutTableCol(positioning_box).IsTableColumn())
    return LayoutSize(cell.Size().Width(), column_height);

  DCHECK(ToLayoutTableCol(positioning_box).IsTableColumnGroup());
  LayoutUnit width = cell.Size().Width();
  ExpandToTableColumnGroup(cell, ToLayoutTableCol(positioning_box), width,
                           kColumnGroupStart);
  ExpandToTableColumnGroup(cell, ToLayoutTableCol(positioning_box), width,
                           kColumnGroupEnd);

  return LayoutSize(width, column_height);
}

namespace {

bool ShouldUseFixedAttachment(const FillLayer& fill_layer) {
  if (RuntimeEnabledFeatures::FastMobileScrollingEnabled()) {
    // As a side effect of an optimization to blit on scroll, we do not honor
    // the CSS property "background-attachment: fixed" because it may result in
    // rendering artifacts. Note, these artifacts only appear if we are blitting
    // on scroll of a page that has fixed background images.
    return false;
  }
  return fill_layer.Attachment() == EFillAttachment::kFixed;
}

LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
                                          const LayoutBoxModelObject* container,
                                          const GlobalPaintFlags flags) {
  LocalFrameView* frame_view = obj.View()->GetFrameView();
  if (!frame_view)
    return LayoutRect();

  ScrollableArea* layout_viewport = frame_view->LayoutViewport();
  DCHECK(layout_viewport);

  LayoutRect rect = LayoutRect(
      LayoutPoint(), LayoutSize(layout_viewport->VisibleContentRect().Size()));

  if (FixedBackgroundPaintsInLocalCoordinates(obj, flags))
    return rect;

  // The LayoutView is the only object that can paint a fixed background into
  // its scrolling contents layer, so it gets a special adjustment here.
  if (obj.IsLayoutView()) {
    if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
      DCHECK_EQ(obj.GetBackgroundPaintLocation(),
                kBackgroundPaintInScrollingContents);
      rect.SetLocation(IntPoint(ToLayoutView(obj).ScrolledContentOffset()));
    } else if (auto* mapping = obj.Layer()->GetCompositedLayerMapping()) {
      if (mapping->BackgroundPaintsOntoScrollingContentsLayer())
        rect.SetLocation(IntPoint(ToLayoutView(obj).ScrolledContentOffset()));
    }
  }

  rect.MoveBy(AccumulatedScrollOffsetForFixedBackground(obj, container));

  if (container)
    rect.MoveBy(LayoutPoint(-container->LocalToAbsolute(FloatPoint())));

  // By now we have converted the viewport rect to the border box space of
  // |container|, however |container| does not necessarily create a paint
  // offset translation node, thus its paint offset must be added to convert
  // the rect to the space of the transform node.
  // TODO(trchen): This function does only one simple thing -- mapping the
  // viewport rect from frame space to whatever space the current paint
  // context uses. However we can't always invoke geometry mapper because
  // there are at least one caller uses this before PrePaint phase.
  if (container) {
    DCHECK_GE(container->GetDocument().Lifecycle().GetState(),
              DocumentLifecycle::kPrePaintClean);
    rect.MoveBy(container->FirstFragment().PaintOffset());
  }

  return rect;
}

}  // Anonymous namespace

BackgroundImageGeometry::BackgroundImageGeometry(const LayoutView& view)
    : box_(view),
      positioning_box_(view.RootBox()),
      has_non_local_geometry_(false),
      painting_view_(true),
      painting_table_cell_(false),
      cell_using_container_background_(false) {
  // The background of the box generated by the root element covers the
  // entire canvas and will be painted by the view object, but the we should
  // still use the root element box for positioning.
  positioning_size_override_ = view.RootBox().Size();
}

BackgroundImageGeometry::BackgroundImageGeometry(
    const LayoutBoxModelObject& obj)
    : box_(obj),
      positioning_box_(obj),
      has_non_local_geometry_(false),
      painting_view_(false),
      painting_table_cell_(false),
      cell_using_container_background_(false) {
  // Specialized constructor should be used for LayoutView.
  DCHECK(!obj.IsLayoutView());
}

BackgroundImageGeometry::BackgroundImageGeometry(
    const LayoutTableCell& cell,
    const LayoutObject* background_object)
    : box_(cell),
      positioning_box_(background_object && !background_object->IsTableCell()
                           ? ToLayoutBoxModelObject(*background_object)
                           : cell),
      has_non_local_geometry_(false),
      painting_view_(false),
      painting_table_cell_(true) {
  cell_using_container_background_ =
      background_object && !background_object->IsTableCell();
  if (cell_using_container_background_) {
    offset_in_background_ =
        GetOffsetForCell(cell, ToLayoutBox(*background_object));
    positioning_size_override_ =
        GetBackgroundObjectDimensions(cell, ToLayoutBox(*background_object));
  }
}

void BackgroundImageGeometry::ComputeDestRectAdjustments(
    const FillLayer& fill_layer,
    const LayoutRect& unsnapped_positioning_area,
    bool disallow_border_derived_adjustment,
    LayoutRectOutsets& unsnapped_dest_adjust,
    LayoutRectOutsets& snapped_dest_adjust) const {
  switch (fill_layer.Clip()) {
    case EFillBox::kContent:
      // If the PaddingOutsets are zero then this is equivalent to
      // kPadding and we should apply the snapping logic.
      if (!positioning_box_.PaddingOutsets().IsZero()) {
        unsnapped_dest_adjust = positioning_box_.PaddingOutsets();
        unsnapped_dest_adjust += positioning_box_.BorderBoxOutsets();

        // We're not trying to match a border position, so don't snap.
        snapped_dest_adjust = unsnapped_dest_adjust;
        return;
      }
      FALLTHROUGH;
    case EFillBox::kPadding:
      unsnapped_dest_adjust = positioning_box_.BorderBoxOutsets();
      if (disallow_border_derived_adjustment) {
        // Nothing to drive snapping behavior, so don't snap.
        snapped_dest_adjust = unsnapped_dest_adjust;
      } else {
        // Force the snapped dest rect to match the inner border to
        // avoid gaps between the background and border.
        // TODO(schenney) The LayoutUnit(float) constructor always
        // rounds down. We should FromFloatFloor or FromFloatCeil to
        // move toward the border.
        FloatRect inner_border_rect =
            positioning_box_.StyleRef()
                .GetRoundedInnerBorderFor(unsnapped_positioning_area)
                .Rect();
        snapped_dest_adjust.SetLeft(LayoutUnit(inner_border_rect.X()) -
                                    unsnapped_dest_rect_.X());
        snapped_dest_adjust.SetTop(LayoutUnit(inner_border_rect.Y()) -
                                   unsnapped_dest_rect_.Y());
        snapped_dest_adjust.SetRight(unsnapped_dest_rect_.MaxX() -
                                     LayoutUnit(inner_border_rect.MaxX()));
        snapped_dest_adjust.SetBottom(unsnapped_dest_rect_.MaxY() -
                                      LayoutUnit(inner_border_rect.MaxY()));
      }
      return;
    case EFillBox::kBorder: {
      if (disallow_border_derived_adjustment) {
        // All adjustments remain 0.
        return;
      }

      // The dest rects can be adjusted. The snapped dest rect is forced
      // to match the inner border to avoid gaps between the background and
      // border, while the unsnapped dest moves according to the
      // border box outsets. This leaves the unsnapped dest accurately
      // conveying the content creator's intent when used for determining
      // the pixels to use from sprite maps and other size and positioning
      // properties.
      // Note that the snapped adjustments do not have the same effect as
      // pixel snapping the unsnapped rectangle. Border snapping snaps both
      // the size and position of the borders, sometimes adjusting the inner
      // border by more than a pixel when done (particularly under magnifying
      // zoom).
      // TODO(schenney) The LayoutUnit(float) constructor always
      // rounds down. We should FromFloatFloor or FromFloatCeil to
      // move toward the border.
      BorderEdge edges[4];
      positioning_box_.StyleRef().GetBorderEdgeInfo(edges);
      FloatRect inner_border_rect =
          positioning_box_.StyleRef()
              .GetRoundedInnerBorderFor(unsnapped_positioning_area)
              .Rect();
      LayoutRectOutsets box_outsets = positioning_box_.BorderBoxOutsets();
      if (edges[static_cast<unsigned>(BoxSide::kTop)].ObscuresBackground()) {
        snapped_dest_adjust.SetTop(LayoutUnit(inner_border_rect.Y()) -
                                   unsnapped_dest_rect_.Y());
        unsnapped_dest_adjust.SetTop(box_outsets.Top());
      }
      if (edges[static_cast<unsigned>(BoxSide::kRight)].ObscuresBackground()) {
        snapped_dest_adjust.SetRight(unsnapped_dest_rect_.MaxX() -
                                     LayoutUnit(inner_border_rect.MaxX()));
        unsnapped_dest_adjust.SetRight(box_outsets.Right());
      }
      if (edges[static_cast<unsigned>(BoxSide::kBottom)].ObscuresBackground()) {
        snapped_dest_adjust.SetBottom(unsnapped_dest_rect_.MaxY() -
                                      LayoutUnit(inner_border_rect.MaxY()));
        unsnapped_dest_adjust.SetBottom(box_outsets.Bottom());
      }
      if (edges[static_cast<unsigned>(BoxSide::kLeft)].ObscuresBackground()) {
        snapped_dest_adjust.SetLeft(LayoutUnit(inner_border_rect.X()) -
                                    unsnapped_dest_rect_.X());
        unsnapped_dest_adjust.SetLeft(box_outsets.Left());
      }
    }
      return;
    case EFillBox::kText:
      return;
  }
}

void BackgroundImageGeometry::ComputePositioningAreaAdjustments(
    const FillLayer& fill_layer,
    const LayoutRect& unsnapped_positioning_area,
    bool disallow_border_derived_adjustment,
    LayoutRectOutsets& unsnapped_box_outset,
    LayoutRectOutsets& snapped_box_outset) const {
  switch (fill_layer.Origin()) {
    case EFillBox::kContent:
      // If the PaddingOutsets are zero then this is equivalent to
      // kPadding and we should apply the snapping logic.
      if (!positioning_box_.PaddingOutsets().IsZero()) {
        unsnapped_box_outset = positioning_box_.PaddingOutsets();
        unsnapped_box_outset += positioning_box_.BorderBoxOutsets();

        // We're not trying to match a border position, so don't snap.
        snapped_box_outset = unsnapped_box_outset;
        return;
      }
      FALLTHROUGH;
    case EFillBox::kPadding:
      unsnapped_box_outset = positioning_box_.BorderBoxOutsets();
      if (disallow_border_derived_adjustment) {
        snapped_box_outset = unsnapped_box_outset;
      } else {
        // Force the snapped positioning area to fill to the borders.
        // Note that the snapped adjustments do not have the same effect as
        // pixel snapping the unsnapped rectangle. Border snapping snaps both
        // the size and position of the borders, sometimes adjusting the inner
        // border by more than a pixel when done (particularly under magnifying
        // zoom).
        FloatRect inner_border_rect =
            positioning_box_.StyleRef()
                .GetRoundedInnerBorderFor(unsnapped_positioning_area)
                .Rect();
        snapped_box_outset.SetLeft(LayoutUnit(inner_border_rect.X()) -
                                   unsnapped_positioning_area.X());
        snapped_box_outset.SetTop(LayoutUnit(inner_border_rect.Y()) -
                                  unsnapped_positioning_area.Y());
        snapped_box_outset.SetRight(unsnapped_positioning_area.MaxX() -
                                    LayoutUnit(inner_border_rect.MaxX()));
        snapped_box_outset.SetBottom(unsnapped_positioning_area.MaxY() -
                                     LayoutUnit(inner_border_rect.MaxY()));
      }
      return;
    case EFillBox::kBorder:
      // All adjustments remain 0.
      snapped_box_outset = unsnapped_box_outset = LayoutRectOutsets(0, 0, 0, 0);
      return;
    case EFillBox::kText:
      return;
  }
}

void BackgroundImageGeometry::ComputePositioningArea(
    const LayoutBoxModelObject* container,
    PaintPhase paint_phase,
    GlobalPaintFlags flags,
    const FillLayer& fill_layer,
    const LayoutRect& paint_rect,
    LayoutRect& unsnapped_positioning_area,
    LayoutRect& snapped_positioning_area,
    LayoutPoint& unsnapped_box_offset,
    LayoutPoint& snapped_box_offset) {
  if (ShouldUseFixedAttachment(fill_layer)) {
    // No snapping for fixed attachment.
    SetHasNonLocalGeometry();
    offset_in_background_ = LayoutPoint();
    unsnapped_positioning_area =
        FixedAttachmentPositioningArea(box_, container, flags);
    unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
        unsnapped_positioning_area;
  } else {
    unsnapped_dest_rect_ = paint_rect;

    if (painting_view_ || cell_using_container_background_)
      unsnapped_positioning_area.SetSize(positioning_size_override_);
    else
      unsnapped_positioning_area = unsnapped_dest_rect_;

    // Attempt to shrink the destination rect if possible while also ensuring
    // that it paints to the border:
    //
    //   * for background-clip content-box/padding-box, we can restrict to the
    //     respective box, but for padding-box we also try to force alignment
    //     with the inner border.
    //
    //   * for border-box, we can modify individual edges iff the border fully
    //     obscures the background.
    //
    // It is unsafe to derive dest from border information when any of the
    // following is true:
    // * the layer is not painted as part of a regular background phase
    //  (e.g.paint_phase == kMask)
    // * non-SrcOver compositing is active
    // * painting_view_ is set, meaning we're dealing with a
    //   LayoutView - for which dest rect is overflowing (expanded to cover
    //   the whole canvas).
    // * We are painting table cells using the table background, or the table
    //   has collapsed borders
    // * There is a border image, because it may not be opaque or may be outset.
    bool disallow_border_derived_adjustment =
        !ShouldPaintSelfBlockBackground(paint_phase) ||
        fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
        painting_view_ || painting_table_cell_ ||
        positioning_box_.StyleRef().BorderImage().GetImage() ||
        positioning_box_.StyleRef().BorderCollapse() ==
            EBorderCollapse::kCollapse;

    // Compute all the outsets we need to apply to the rectangles. These
    // outsets also include the snapping behavior.
    LayoutRectOutsets unsnapped_dest_adjust;
    LayoutRectOutsets snapped_dest_adjust;
    LayoutRectOutsets unsnapped_box_outset;
    LayoutRectOutsets snapped_box_outset;
    ComputeDestRectAdjustments(fill_layer, unsnapped_positioning_area,
                               disallow_border_derived_adjustment,
                               unsnapped_dest_adjust, snapped_dest_adjust);
    ComputePositioningAreaAdjustments(fill_layer, unsnapped_positioning_area,
                                      disallow_border_derived_adjustment,
                                      unsnapped_box_outset, snapped_box_outset);

    // Apply the adjustments.
    snapped_dest_rect_ = unsnapped_dest_rect_;
    snapped_dest_rect_.Contract(snapped_dest_adjust);
    snapped_dest_rect_ = LayoutRect(PixelSnappedIntRect(snapped_dest_rect_));
    unsnapped_dest_rect_.Contract(unsnapped_dest_adjust);
    snapped_positioning_area = unsnapped_positioning_area;
    snapped_positioning_area.Contract(snapped_box_outset);
    snapped_positioning_area =
        LayoutRect(PixelSnappedIntRect(snapped_positioning_area));
    unsnapped_positioning_area.Contract(unsnapped_box_outset);

    // Offset of the positioning area from the corner of the
    // positioning_box_.
    // TODO(schenney): Could we enable dest adjust for collapsed
    // borders if we computed this based on the actual offset between
    // the rects?
    unsnapped_box_offset =
        LayoutPoint(unsnapped_box_outset.Left() - unsnapped_dest_adjust.Left(),
                    unsnapped_box_outset.Top() - unsnapped_dest_adjust.Top());
    snapped_box_offset =
        LayoutPoint(snapped_box_outset.Left() - snapped_dest_adjust.Left(),
                    snapped_box_outset.Top() - snapped_dest_adjust.Top());
    // For view backgrounds, the input paint rect is specified in root element
    // local coordinate (i.e. a transform is applied on the context for
    // painting), and is expanded to cover the whole canvas. Since left/top is
    // relative to the paint rect, we need to offset them back.
    if (painting_view_) {
      unsnapped_box_offset -= paint_rect.Location();
      snapped_box_offset -= paint_rect.Location();
    }
  }
}

void BackgroundImageGeometry::CalculateFillTileSize(
    const FillLayer& fill_layer,
    const LayoutSize& unsnapped_positioning_area_size,
    const LayoutSize& snapped_positioning_area_size) {
  StyleImage* image = fill_layer.GetImage();
  EFillSizeType type = fill_layer.SizeType();

  // Tile size is snapped for images without intrinsic dimensions (typically
  // generated content) and unsnapped for content that has intrinsic
  // dimensions. Once we choose here we stop tracking whether the tile size is
  // snapped or unsnapped.
  LayoutSize positioning_area_size = !image->HasIntrinsicSize()
                                         ? snapped_positioning_area_size
                                         : unsnapped_positioning_area_size;
  LayoutSize image_intrinsic_size(image->ImageSize(
      positioning_box_.GetDocument(),
      positioning_box_.StyleRef().EffectiveZoom(), positioning_area_size));
  switch (type) {
    case EFillSizeType::kSizeLength: {
      tile_size_ = positioning_area_size;

      const Length& layer_width = fill_layer.SizeLength().Width();
      const Length& layer_height = fill_layer.SizeLength().Height();

      if (layer_width.IsFixed()) {
        tile_size_.SetWidth(LayoutUnit(layer_width.Value()));
      } else if (layer_width.IsPercentOrCalc()) {
        tile_size_.SetWidth(
            ValueForLength(layer_width, positioning_area_size.Width()));
      }

      if (layer_height.IsFixed()) {
        tile_size_.SetHeight(LayoutUnit(layer_height.Value()));
      } else if (layer_height.IsPercentOrCalc()) {
        tile_size_.SetHeight(
            ValueForLength(layer_height, positioning_area_size.Height()));
      }

      // If one of the values is auto we have to use the appropriate
      // scale to maintain our aspect ratio.
      if (layer_width.IsAuto() && !layer_height.IsAuto()) {
        if (!image->HasIntrinsicSize()) {
          // Spec says that auto should be 100% in the absence of
          // an intrinsic ratio or size.
          tile_size_.SetWidth(positioning_area_size.Width());
        } else if (image_intrinsic_size.Height()) {
          float adjusted_width = image_intrinsic_size.Width().ToFloat() /
                                 image_intrinsic_size.Height().ToFloat() *
                                 tile_size_.Height().ToFloat();
          if (image_intrinsic_size.Width() >= 1 && adjusted_width < 1)
            adjusted_width = 1;
          tile_size_.SetWidth(LayoutUnit(adjusted_width));
        }
      } else if (!layer_width.IsAuto() && layer_height.IsAuto()) {
        if (!image->HasIntrinsicSize()) {
          // Spec says that auto should be 100% in the absence of
          // an intrinsic ratio or size.
          tile_size_.SetHeight(positioning_area_size.Height());
        } else if (image_intrinsic_size.Width()) {
          float adjusted_height = image_intrinsic_size.Height().ToFloat() /
                                  image_intrinsic_size.Width().ToFloat() *
                                  tile_size_.Width().ToFloat();
          if (image_intrinsic_size.Height() >= 1 && adjusted_height < 1)
            adjusted_height = 1;
          tile_size_.SetHeight(LayoutUnit(adjusted_height));
        }
      } else if (layer_width.IsAuto() && layer_height.IsAuto()) {
        // If both width and height are auto, use the image's intrinsic size.
        tile_size_ = image_intrinsic_size;
      }

      tile_size_.ClampNegativeToZero();
      return;
    }
    case EFillSizeType::kContain:
    case EFillSizeType::kCover: {
      // Always use the snapped positioning area size for this computation,
      // so that we resize the image to completely fill the actual painted
      // area.
      float horizontal_scale_factor =
          image_intrinsic_size.Width()
              ? snapped_positioning_area_size.Width().ToFloat() /
                    image_intrinsic_size.Width()
              : 1.0f;
      float vertical_scale_factor =
          image_intrinsic_size.Height()
              ? snapped_positioning_area_size.Height().ToFloat() /
                    image_intrinsic_size.Height()
              : 1.0f;
      // Force the dimension that determines the size to exactly match the
      // positioning_area_size in that dimension, so that rounding of floating
      // point approximation to LayoutUnit do not shrink the image to smaller
      // than the positioning_area_size.
      if (type == EFillSizeType::kContain) {
        // Snap the dependent dimension to avoid bleeding/blending artifacts
        // at the edge of the image when we paint it.
        if (horizontal_scale_factor < vertical_scale_factor) {
          tile_size_ = LayoutSize(
              snapped_positioning_area_size.Width(),
              LayoutUnit(std::max(1.0f, roundf(image_intrinsic_size.Height() *
                                               horizontal_scale_factor))));
        } else {
          tile_size_ = LayoutSize(
              LayoutUnit(std::max(1.0f, roundf(image_intrinsic_size.Width() *
                                               vertical_scale_factor))),
              snapped_positioning_area_size.Height());
        }
        return;
      }
      if (horizontal_scale_factor > vertical_scale_factor) {
        tile_size_ =
            LayoutSize(snapped_positioning_area_size.Width(),
                       LayoutUnit(std::max(1.0f, image_intrinsic_size.Height() *
                                                     horizontal_scale_factor)));
      } else {
        tile_size_ =
            LayoutSize(LayoutUnit(std::max(1.0f, image_intrinsic_size.Width() *
                                                     vertical_scale_factor)),
                       snapped_positioning_area_size.Height());
      }
      return;
    }
    case EFillSizeType::kSizeNone:
      // This value should only be used while resolving style.
      NOTREACHED();
  }

  NOTREACHED();
  return;
}

void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
                                        PaintPhase paint_phase,
                                        GlobalPaintFlags flags,
                                        const FillLayer& fill_layer,
                                        const LayoutRect& paint_rect) {
  // Unsnapped positioning area is used to derive quantities
  // that reference source image maps and define non-integer values, such
  // as phase and position.
  LayoutRect unsnapped_positioning_area;

  // Snapped positioning area is used for sizing images based on the
  // background area (like cover and contain), and for setting the repeat
  // spacing.
  LayoutRect snapped_positioning_area;

  // Additional offset from the corner of the positioning_box_
  LayoutPoint unsnapped_box_offset;
  LayoutPoint snapped_box_offset;

  // This method also sets the destination rects.
  ComputePositioningArea(container, paint_phase, flags, fill_layer, paint_rect,
                         unsnapped_positioning_area, snapped_positioning_area,
                         unsnapped_box_offset, snapped_box_offset);

  // Sets the tile_size_.
  CalculateFillTileSize(fill_layer, unsnapped_positioning_area.Size(),
                        snapped_positioning_area.Size());

  EFillRepeat background_repeat_x = fill_layer.RepeatX();
  EFillRepeat background_repeat_y = fill_layer.RepeatY();

  // Maintain both snapped and unsnapped available widths and heights.
  // Unsnapped values are used for most thing, but snapped are used
  // to computed sizes that must fill the area, such as round and space.
  LayoutUnit unsnapped_available_width =
      unsnapped_positioning_area.Width() - tile_size_.Width();
  LayoutUnit unsnapped_available_height =
      unsnapped_positioning_area.Height() - tile_size_.Height();
  LayoutUnit snapped_available_width =
      snapped_positioning_area.Width() - tile_size_.Width();
  LayoutUnit snapped_available_height =
      snapped_positioning_area.Height() - tile_size_.Height();
  LayoutSize snapped_positioning_area_size = snapped_positioning_area.Size();

  // Computed position is for placing things within the destination, so use
  // snapped values.
  LayoutUnit computed_x_position =
      MinimumValueForLength(fill_layer.PositionX(), snapped_available_width) -
      offset_in_background_.X();
  LayoutUnit computed_y_position =
      MinimumValueForLength(fill_layer.PositionY(), snapped_available_height) -
      offset_in_background_.Y();

  if (background_repeat_x == EFillRepeat::kRoundFill &&
      snapped_positioning_area_size.Width() > LayoutUnit() &&
      tile_size_.Width() > LayoutUnit()) {
    int nr_tiles = std::max(
        1,
        RoundToInt(snapped_positioning_area_size.Width() / tile_size_.Width()));
    LayoutUnit rounded_width = snapped_positioning_area_size.Width() / nr_tiles;

    // Maintain aspect ratio if background-size: auto is set
    if (fill_layer.SizeLength().Height().IsAuto() &&
        background_repeat_y != EFillRepeat::kRoundFill) {
      tile_size_.SetHeight(tile_size_.Height() * rounded_width /
                           tile_size_.Width());
    }
    tile_size_.SetWidth(rounded_width);

    // Force the first tile to line up with the edge of the positioning area.
    SetPhaseX(tile_size_.Width()
                  ? tile_size_.Width() -
                        fmodf(computed_x_position + unsnapped_box_offset.X(),
                              tile_size_.Width())
                  : 0);
    SetSpaceSize(LayoutSize());
  }

  if (background_repeat_y == EFillRepeat::kRoundFill &&
      snapped_positioning_area_size.Height() > LayoutUnit() &&
      tile_size_.Height() > LayoutUnit()) {
    int nr_tiles =
        std::max(1, RoundToInt(snapped_positioning_area_size.Height() /
                               tile_size_.Height()));
    LayoutUnit rounded_height =
        snapped_positioning_area_size.Height() / nr_tiles;
    // Maintain aspect ratio if background-size: auto is set
    if (fill_layer.SizeLength().Width().IsAuto() &&
        background_repeat_x != EFillRepeat::kRoundFill) {
      tile_size_.SetWidth(tile_size_.Width() * rounded_height /
                          tile_size_.Height());
    }
    tile_size_.SetHeight(rounded_height);

    // Force the first tile to line up with the edge of the positioning area.
    SetPhaseY(tile_size_.Height()
                  ? tile_size_.Height() -
                        fmodf(computed_y_position + unsnapped_box_offset.Y(),
                              tile_size_.Height())
                  : 0);
    SetSpaceSize(LayoutSize());
  }

  if (background_repeat_x == EFillRepeat::kRepeatFill) {
    // Repeat must set the phase accurately, so use unsnapped values.
    SetRepeatX(fill_layer, unsnapped_available_width, unsnapped_box_offset.X());
  } else if (background_repeat_x == EFillRepeat::kSpaceFill &&
             tile_size_.Width() > LayoutUnit()) {
    // SpaceFill uses snapped values to fill the painted area.
    LayoutUnit space = GetSpaceBetweenImageTiles(
        snapped_positioning_area_size.Width(), tile_size_.Width());
    if (space >= LayoutUnit())
      SetSpaceX(space, snapped_box_offset.X());
    else
      background_repeat_x = EFillRepeat::kNoRepeatFill;
  }
  if (background_repeat_x == EFillRepeat::kNoRepeatFill) {
    // NoRepeat moves the dest rects, so needs both snapped and
    // unsnapped parameters.
    LayoutUnit x_offset =
        fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight
            ? unsnapped_available_width - computed_x_position
            : computed_x_position;
    LayoutUnit snapped_x_offset =
        fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight
            ? snapped_available_width - computed_x_position
            : computed_x_position;
    SetNoRepeatX(fill_layer, unsnapped_box_offset.X() + x_offset,
                 snapped_box_offset.X() + snapped_x_offset);
    if (offset_in_background_.X() > tile_size_.Width())
      unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
  }

  if (background_repeat_y == EFillRepeat::kRepeatFill) {
    // Repeat must set the phase accurately, so use unsnapped values.
    SetRepeatY(fill_layer, unsnapped_available_height,
               unsnapped_box_offset.Y());
  } else if (background_repeat_y == EFillRepeat::kSpaceFill &&
             tile_size_.Height() > LayoutUnit()) {
    // SpaceFill uses snapped values to fill the painted area.
    LayoutUnit space = GetSpaceBetweenImageTiles(
        snapped_positioning_area_size.Height(), tile_size_.Height());
    if (space >= LayoutUnit())
      SetSpaceY(space, snapped_box_offset.Y());
    else
      background_repeat_y = EFillRepeat::kNoRepeatFill;
  }
  if (background_repeat_y == EFillRepeat::kNoRepeatFill) {
    // NoRepeat moves the dest rects, so needs both snapped and
    // unsnapped parameters.
    LayoutUnit y_offset =
        fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom
            ? unsnapped_available_height - computed_y_position
            : computed_y_position;
    LayoutUnit snapped_y_offset =
        fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom
            ? snapped_available_height - computed_y_position
            : computed_y_position;
    SetNoRepeatY(fill_layer, unsnapped_box_offset.Y() + y_offset,
                 snapped_box_offset.Y() + snapped_y_offset);
    if (offset_in_background_.Y() > tile_size_.Height())
      unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
  }

  if (ShouldUseFixedAttachment(fill_layer))
    UseFixedAttachment(paint_rect.Location());

  // Clip the final output rect to the paint rect, maintaining snapping.
  unsnapped_dest_rect_.Intersect(paint_rect);
  snapped_dest_rect_.Intersect(LayoutRect(PixelSnappedIntRect(paint_rect)));
}

const ImageResourceObserver& BackgroundImageGeometry::ImageClient() const {
  return painting_view_ ? box_ : positioning_box_;
}

const Document& BackgroundImageGeometry::ImageDocument() const {
  return box_.GetDocument();
}

const ComputedStyle& BackgroundImageGeometry::ImageStyle() const {
  const bool use_style_from_positioning_box =
      painting_view_ || cell_using_container_background_;
  return (use_style_from_positioning_box ? positioning_box_ : box_).StyleRef();
}

InterpolationQuality BackgroundImageGeometry::ImageInterpolationQuality()
    const {
  return box_.StyleRef().GetInterpolationQuality();
}

}  // namespace blink
