// Copyright 2015 The Chromium Authors
// 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/nine_piece_image_grid.h"

#include "third_party/blink/renderer/core/layout/geometry/box_strut.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "ui/gfx/geometry/outsets.h"

namespace blink {

namespace {

LayoutUnit ComputeEdgeWidth(const BorderImageLength& border_slice,
                            int border_side,
                            float image_side,
                            int box_extent) {
  if (border_slice.IsNumber())
    return LayoutUnit(border_slice.Number() * border_side);
  if (border_slice.length().IsAuto())
    return LayoutUnit(image_side);
  return ValueForLength(border_slice.length(), LayoutUnit(box_extent));
}

float ComputeEdgeSlice(const Length& slice, float slice_scale, float maximum) {
  float resolved;
  // If the slice is a <number> (stored as a fixed Length), scale it by the
  // slice scale to get to the same space as the image.
  if (slice.IsFixed()) {
    resolved = slice.Value() * slice_scale;
  } else {
    DCHECK(slice.IsPercent());
    resolved = FloatValueForLength(slice, maximum);
  }
  resolved = std::min(maximum, resolved);
  // Round-trip via LayoutUnit to flush out any "excess" precision.
  return LayoutUnit::FromFloatRound(resolved).ToFloat();
}

// "Round" the edge widths, adhering to the following restrictions:
//
//  1) Perform rounding in the same way as for borders, thus preferring
//     symmetry.
//
//  2) If edges are abutting, then distribute the space (i.e the single pixel)
//     to the edge with the highest coverage - giving the starting edge
//     precedence if tied.
//
gfx::Outsets SnapEdgeWidths(const PhysicalBoxStrut& edge_widths,
                            const gfx::Size& snapped_box_size) {
  gfx::Outsets snapped;
  // Allow a small deviation when checking if the the edges are abutting.
  constexpr LayoutUnit kAbuttingEpsilon(LayoutUnit::Epsilon());
  if (snapped_box_size.width() - edge_widths.HorizontalSum() <=
      kAbuttingEpsilon) {
    snapped.set_left(edge_widths.left.Round());
    snapped.set_right(snapped_box_size.width() - snapped.left());
  } else {
    snapped.set_left(edge_widths.left.Floor());
    snapped.set_right(edge_widths.right.Floor());
  }
  DCHECK_LE(snapped.left() + snapped.right(), snapped_box_size.width());

  if (snapped_box_size.height() - edge_widths.VerticalSum() <=
      kAbuttingEpsilon) {
    snapped.set_top(edge_widths.top.Round());
    snapped.set_bottom(snapped_box_size.height() - snapped.top());
  } else {
    snapped.set_top(edge_widths.top.Floor());
    snapped.set_bottom(edge_widths.bottom.Floor());
  }
  DCHECK_LE(snapped.top() + snapped.bottom(), snapped_box_size.height());
  return snapped;
}

}  // namespace

NinePieceImageGrid::NinePieceImageGrid(const NinePieceImage& nine_piece_image,
                                       const gfx::SizeF& image_size,
                                       const gfx::Vector2dF& slice_scale,
                                       float zoom,
                                       const gfx::Rect& border_image_area,
                                       const gfx::Outsets& border_widths,
                                       PhysicalBoxSides sides_to_include)
    : border_image_area_(border_image_area),
      image_size_(image_size),
      horizontal_tile_rule_(nine_piece_image.HorizontalRule()),
      vertical_tile_rule_(nine_piece_image.VerticalRule()),
      zoom_(zoom),
      fill_(nine_piece_image.Fill()) {
  const LengthBox& image_slices = nine_piece_image.ImageSlices();
  top_.slice = ComputeEdgeSlice(image_slices.Top(), slice_scale.y(),
                                image_size.height());
  right_.slice = ComputeEdgeSlice(image_slices.Right(), slice_scale.x(),
                                  image_size.width());
  bottom_.slice = ComputeEdgeSlice(image_slices.Bottom(), slice_scale.y(),
                                   image_size.height());
  left_.slice = ComputeEdgeSlice(image_slices.Left(), slice_scale.x(),
                                 image_size.width());

  // |Edge::slice| is in image-local units (physical pixels for raster images),
  // but when using it to resolve 'auto' for border-image-widths we want it to
  // be in zoomed CSS pixels, so divide by |slice_scale| and multiply by zoom.
  const gfx::Vector2dF auto_slice_adjustment(zoom / slice_scale.x(),
                                             zoom / slice_scale.y());
  const BorderImageLengthBox& border_slices = nine_piece_image.BorderSlices();
  PhysicalBoxStrut resolved_widths;
  if (sides_to_include.top) {
    resolved_widths.top = ComputeEdgeWidth(
        border_slices.Top(), border_widths.top(),
        top_.slice * auto_slice_adjustment.y(), border_image_area.height());
  }
  if (sides_to_include.right) {
    resolved_widths.right = ComputeEdgeWidth(
        border_slices.Right(), border_widths.right(),
        right_.slice * auto_slice_adjustment.x(), border_image_area.width());
  }
  if (sides_to_include.bottom) {
    resolved_widths.bottom = ComputeEdgeWidth(
        border_slices.Bottom(), border_widths.bottom(),
        bottom_.slice * auto_slice_adjustment.y(), border_image_area.height());
  }
  if (sides_to_include.left) {
    resolved_widths.left = ComputeEdgeWidth(
        border_slices.Left(), border_widths.left(),
        left_.slice * auto_slice_adjustment.x(), border_image_area.width());
  }

  // The spec says: Given Lwidth as the width of the border image area, Lheight
  // as its height, and Wside as the border image width offset for the side, let
  // f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all
  // W are reduced by multiplying them by f.
  const LayoutUnit border_side_width = resolved_widths.HorizontalSum();
  const LayoutUnit border_side_height = resolved_widths.VerticalSum();
  const float border_side_scale_factor = std::min(
      static_cast<float>(border_image_area.width()) / border_side_width,
      static_cast<float>(border_image_area.height()) / border_side_height);
  if (border_side_scale_factor < 1) {
    resolved_widths.top =
        LayoutUnit(resolved_widths.top * border_side_scale_factor);
    resolved_widths.right =
        LayoutUnit(resolved_widths.right * border_side_scale_factor);
    resolved_widths.bottom =
        LayoutUnit(resolved_widths.bottom * border_side_scale_factor);
    resolved_widths.left =
        LayoutUnit(resolved_widths.left * border_side_scale_factor);
  }

  const gfx::Outsets snapped_widths =
      SnapEdgeWidths(resolved_widths, border_image_area.size());

  top_.width = snapped_widths.top();
  right_.width = snapped_widths.right();
  bottom_.width = snapped_widths.bottom();
  left_.width = snapped_widths.left();
}

// Given a rectangle, construct a subrectangle using offset, width and height.
// Negative offsets are relative to the extent of the given rectangle.
static gfx::RectF Subrect(const gfx::RectF& rect,
                          float offset_x,
                          float offset_y,
                          float width,
                          float height) {
  float base_x = rect.x();
  if (offset_x < 0)
    base_x = rect.right();

  float base_y = rect.y();
  if (offset_y < 0)
    base_y = rect.bottom();

  return gfx::RectF(base_x + offset_x, base_y + offset_y, width, height);
}

static gfx::RectF Subrect(const gfx::Rect& rect,
                          float offset_x,
                          float offset_y,
                          float width,
                          float height) {
  return Subrect(gfx::RectF(rect), offset_x, offset_y, width, height);
}

static gfx::RectF Subrect(const gfx::SizeF& size,
                          float offset_x,
                          float offset_y,
                          float width,
                          float height) {
  return Subrect(gfx::RectF(size), offset_x, offset_y, width, height);
}

static inline void SetCornerPiece(
    NinePieceImageGrid::NinePieceDrawInfo& draw_info,
    bool is_drawable,
    const gfx::RectF& source,
    const gfx::RectF& destination) {
  draw_info.is_drawable = is_drawable;
  if (draw_info.is_drawable) {
    draw_info.source = source;
    draw_info.destination = destination;
  }
}

void NinePieceImageGrid::SetDrawInfoCorner(NinePieceDrawInfo& draw_info,
                                           NinePiece piece) const {
  switch (piece) {
    case kTopLeftPiece:
      SetCornerPiece(
          draw_info, top_.IsDrawable() && left_.IsDrawable(),
          Subrect(image_size_, 0, 0, left_.slice, top_.slice),
          Subrect(border_image_area_, 0, 0, left_.width, top_.width));
      break;
    case kBottomLeftPiece:
      SetCornerPiece(
          draw_info, bottom_.IsDrawable() && left_.IsDrawable(),
          Subrect(image_size_, 0, -bottom_.slice, left_.slice, bottom_.slice),
          Subrect(border_image_area_, 0, -bottom_.width, left_.width,
                  bottom_.width));
      break;
    case kTopRightPiece:
      SetCornerPiece(
          draw_info, top_.IsDrawable() && right_.IsDrawable(),
          Subrect(image_size_, -right_.slice, 0, right_.slice, top_.slice),
          Subrect(border_image_area_, -right_.width, 0, right_.width,
                  top_.width));
      break;
    case kBottomRightPiece:
      SetCornerPiece(draw_info, bottom_.IsDrawable() && right_.IsDrawable(),
                     Subrect(image_size_, -right_.slice, -bottom_.slice,
                             right_.slice, bottom_.slice),
                     Subrect(border_image_area_, -right_.width, -bottom_.width,
                             right_.width, bottom_.width));
      break;
    default:
      NOTREACHED();
      break;
  }
}

static inline void SetHorizontalEdge(
    NinePieceImageGrid::NinePieceDrawInfo& draw_info,
    const NinePieceImageGrid::Edge& edge,
    const gfx::RectF& source,
    const gfx::RectF& destination,
    ENinePieceImageRule tile_rule) {
  draw_info.is_drawable =
      edge.IsDrawable() && source.width() > 0 && destination.width() > 0;
  if (draw_info.is_drawable) {
    draw_info.source = source;
    draw_info.destination = destination;
    draw_info.tile_scale = gfx::Vector2dF(edge.Scale(), edge.Scale());
    draw_info.tile_rule = {tile_rule, kStretchImageRule};
  }
}

static inline void SetVerticalEdge(
    NinePieceImageGrid::NinePieceDrawInfo& draw_info,
    const NinePieceImageGrid::Edge& edge,
    const gfx::RectF& source,
    const gfx::RectF& destination,
    ENinePieceImageRule tile_rule) {
  draw_info.is_drawable =
      edge.IsDrawable() && source.height() > 0 && destination.height() > 0;
  if (draw_info.is_drawable) {
    draw_info.source = source;
    draw_info.destination = destination;
    draw_info.tile_scale = gfx::Vector2dF(edge.Scale(), edge.Scale());
    draw_info.tile_rule = {kStretchImageRule, tile_rule};
  }
}

void NinePieceImageGrid::SetDrawInfoEdge(NinePieceDrawInfo& draw_info,
                                         NinePiece piece) const {
  gfx::SizeF edge_source_size =
      image_size_ -
      gfx::SizeF(left_.slice + right_.slice, top_.slice + bottom_.slice);
  gfx::Size edge_destination_size =
      border_image_area_.size() -
      gfx::Size(left_.width + right_.width, top_.width + bottom_.width);

  switch (piece) {
    case kLeftPiece:
      SetVerticalEdge(draw_info, left_,
                      Subrect(image_size_, 0, top_.slice, left_.slice,
                              edge_source_size.height()),
                      Subrect(border_image_area_, 0, top_.width, left_.width,
                              edge_destination_size.height()),
                      vertical_tile_rule_);
      break;
    case kRightPiece:
      SetVerticalEdge(draw_info, right_,
                      Subrect(image_size_, -right_.slice, top_.slice,
                              right_.slice, edge_source_size.height()),
                      Subrect(border_image_area_, -right_.width, top_.width,
                              right_.width, edge_destination_size.height()),
                      vertical_tile_rule_);
      break;
    case kTopPiece:
      SetHorizontalEdge(draw_info, top_,
                        Subrect(image_size_, left_.slice, 0,
                                edge_source_size.width(), top_.slice),
                        Subrect(border_image_area_, left_.width, 0,
                                edge_destination_size.width(), top_.width),
                        horizontal_tile_rule_);
      break;
    case kBottomPiece:
      SetHorizontalEdge(draw_info, bottom_,
                        Subrect(image_size_, left_.slice, -bottom_.slice,
                                edge_source_size.width(), bottom_.slice),
                        Subrect(border_image_area_, left_.width, -bottom_.width,
                                edge_destination_size.width(), bottom_.width),
                        horizontal_tile_rule_);
      break;
    default:
      NOTREACHED();
      break;
  }
}

void NinePieceImageGrid::SetDrawInfoMiddle(NinePieceDrawInfo& draw_info) const {
  gfx::SizeF source_size = image_size_ - gfx::SizeF(left_.slice + right_.slice,
                                                    top_.slice + bottom_.slice);
  gfx::Size destination_size =
      border_image_area_.size() -
      gfx::Size(left_.width + right_.width, top_.width + bottom_.width);

  draw_info.is_drawable =
      fill_ && !source_size.IsEmpty() && !destination_size.IsEmpty();
  if (!draw_info.is_drawable)
    return;

  draw_info.source = Subrect(image_size_, left_.slice, top_.slice,
                             source_size.width(), source_size.height());
  draw_info.destination =
      Subrect(border_image_area_, left_.width, top_.width,
              destination_size.width(), destination_size.height());

  gfx::Vector2dF middle_scale_factor(zoom_, zoom_);

  if (top_.IsDrawable())
    middle_scale_factor.set_x(top_.Scale());
  else if (bottom_.IsDrawable())
    middle_scale_factor.set_x(bottom_.Scale());

  if (left_.IsDrawable())
    middle_scale_factor.set_y(left_.Scale());
  else if (right_.IsDrawable())
    middle_scale_factor.set_y(right_.Scale());

  if (!source_size.IsEmpty()) {
    // For "stretch" rules, just override the scale factor and replace. We only
    // have to do this for the center tile, since sides don't even use the scale
    // factor unless they have a rule other than "stretch". The middle however
    // can have "stretch" specified in one axis but not the other, so we have to
    // correct the scale here.
    if (horizontal_tile_rule_ == kStretchImageRule) {
      middle_scale_factor.set_x(destination_size.width() / source_size.width());
    }
    if (vertical_tile_rule_ == kStretchImageRule) {
      middle_scale_factor.set_y(destination_size.height() /
                                source_size.height());
    }
  }

  draw_info.tile_scale = middle_scale_factor;
  draw_info.tile_rule = {horizontal_tile_rule_, vertical_tile_rule_};
}

NinePieceImageGrid::NinePieceDrawInfo NinePieceImageGrid::GetNinePieceDrawInfo(
    NinePiece piece) const {
  NinePieceDrawInfo draw_info;
  draw_info.is_corner_piece =
      piece == kTopLeftPiece || piece == kTopRightPiece ||
      piece == kBottomLeftPiece || piece == kBottomRightPiece;

  if (draw_info.is_corner_piece)
    SetDrawInfoCorner(draw_info, piece);
  else if (piece != kMiddlePiece)
    SetDrawInfoEdge(draw_info, piece);
  else
    SetDrawInfoMiddle(draw_info);

  return draw_info;
}

}  // namespace blink
