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


import 'dart:math' as math;

import 'package:flutter/foundation.dart';

import 'basic_types.dart';

/// How a box should be inscribed into another box.
///
/// See also:
///
///  * [applyBoxFit], which applies the sizing semantics of these values (though
///    not the alignment semantics).
enum BoxFit {
  /// Fill the target box by distorting the source's aspect ratio.
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fill.png)
  fill,

  /// As large as possible while still containing the source entirely within the
  /// target box.
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_contain.png)
  contain,

  /// As small as possible while still covering the entire target box.
  ///
  /// {@template flutter.painting.BoxFit.cover}
  /// To actually clip the content, use `clipBehavior: Clip.hardEdge` alongside
  /// this in a [FittedBox].
  /// {@endtemplate}
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_cover.png)
  cover,

  /// Make sure the full width of the source is shown, regardless of
  /// whether this means the source overflows the target box vertically.
  ///
  /// {@macro flutter.painting.BoxFit.cover}
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitWidth.png)
  fitWidth,

  /// Make sure the full height of the source is shown, regardless of
  /// whether this means the source overflows the target box horizontally.
  ///
  /// {@macro flutter.painting.BoxFit.cover}
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitHeight.png)
  fitHeight,

  /// Align the source within the target box (by default, centering) and discard
  /// any portions of the source that lie outside the box.
  ///
  /// The source image is not resized.
  ///
  /// {@macro flutter.painting.BoxFit.cover}
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_none.png)
  none,

  /// Align the source within the target box (by default, centering) and, if
  /// necessary, scale the source down to ensure that the source fits within the
  /// box.
  ///
  /// This is the same as `contain` if that would shrink the image, otherwise it
  /// is the same as `none`.
  ///
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_scaleDown.png)
  scaleDown,
}

/// The pair of sizes returned by [applyBoxFit].
@immutable
class FittedSizes {
  /// Creates an object to store a pair of sizes,
  /// as would be returned by [applyBoxFit].
  const FittedSizes(this.source, this.destination);

  /// The size of the part of the input to show on the output.
  final Size source;

  /// The size of the part of the output on which to show the input.
  final Size destination;
}

/// Apply a [BoxFit] value.
///
/// The arguments to this method, in addition to the [BoxFit] value to apply,
/// are two sizes, ostensibly the sizes of an input box and an output box.
/// Specifically, the `inputSize` argument gives the size of the complete source
/// that is being fitted, and the `outputSize` gives the size of the rectangle
/// into which the source is to be drawn.
///
/// This function then returns two sizes, combined into a single [FittedSizes]
/// object.
///
/// The [FittedSizes.source] size is the subpart of the `inputSize` that is to
/// be shown. If the entire input source is shown, then this will equal the
/// `inputSize`, but if the input source is to be cropped down, this may be
/// smaller.
///
/// The [FittedSizes.destination] size is the subpart of the `outputSize` in
/// which to paint the (possibly cropped) source. If the
/// [FittedSizes.destination] size is smaller than the `outputSize` then the
/// source is being letterboxed (or pillarboxed).
///
/// This method does not express an opinion regarding the alignment of the
/// source and destination sizes within the input and output rectangles.
/// Typically they are centered (this is what [BoxDecoration] does, for
/// instance, and is how [BoxFit] is defined). The [Alignment] class provides a
/// convenience function, [Alignment.inscribe], for resolving the sizes to
/// rects, as shown in the example below.
///
/// {@tool snippet}
///
/// This function paints a [dart:ui.Image] `image` onto the [Rect] `outputRect` on a
/// [Canvas] `canvas`, using a [Paint] `paint`, applying the [BoxFit] algorithm
/// `fit`:
///
/// ```dart
/// void paintImage(ui.Image image, Rect outputRect, Canvas canvas, Paint paint, BoxFit fit) {
///   final Size imageSize = Size(image.width.toDouble(), image.height.toDouble());
///   final FittedSizes sizes = applyBoxFit(fit, imageSize, outputRect.size);
///   final Rect inputSubrect = Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
///   final Rect outputSubrect = Alignment.center.inscribe(sizes.destination, outputRect);
///   canvas.drawImageRect(image, inputSubrect, outputSubrect, paint);
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [FittedBox], a widget that applies this algorithm to another widget.
///  * [paintImage], a function that applies this algorithm to images for painting.
///  * [DecoratedBox], [BoxDecoration], and [DecorationImage], which together
///    provide access to [paintImage] at the widgets layer.
FittedSizes applyBoxFit(BoxFit fit, Size inputSize, Size outputSize) {
  if (inputSize.height <= 0.0 || inputSize.width <= 0.0 || outputSize.height <= 0.0 || outputSize.width <= 0.0)
    return const FittedSizes(Size.zero, Size.zero);

  Size sourceSize, destinationSize;
  switch (fit) {
    case BoxFit.fill:
      sourceSize = inputSize;
      destinationSize = outputSize;
      break;
    case BoxFit.contain:
      sourceSize = inputSize;
      if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height)
        destinationSize = Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height);
      else
        destinationSize = Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width);
      break;
    case BoxFit.cover:
      if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) {
        sourceSize = Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width);
      } else {
        sourceSize = Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height);
      }
      destinationSize = outputSize;
      break;
    case BoxFit.fitWidth:
      sourceSize = Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width);
      destinationSize = Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width);
      break;
    case BoxFit.fitHeight:
      sourceSize = Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height);
      destinationSize = Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height);
      break;
    case BoxFit.none:
      sourceSize = Size(math.min(inputSize.width, outputSize.width), math.min(inputSize.height, outputSize.height));
      destinationSize = sourceSize;
      break;
    case BoxFit.scaleDown:
      sourceSize = inputSize;
      destinationSize = inputSize;
      final double aspectRatio = inputSize.width / inputSize.height;
      if (destinationSize.height > outputSize.height)
        destinationSize = Size(outputSize.height * aspectRatio, outputSize.height);
      if (destinationSize.width > outputSize.width)
        destinationSize = Size(outputSize.width, outputSize.width / aspectRatio);
      break;
  }
  return FittedSizes(sourceSize, destinationSize);
}
