/*
 * Copyright (C) 2007 Apple Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/platform/drag_image.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
#include "third_party/blink/renderer/platform/fonts/string_truncator.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/bidi_text_run.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace blink {

namespace {

const float kDragLabelBorderX = 4;
// Keep border_y in synch with DragController::LinkDragBorderInset.
const float kDragLabelBorderY = 2;
const float kLabelBorderYOffset = 2;

const float kMaxDragLabelWidth = 300;
const float kMaxDragLabelStringWidth =
    (kMaxDragLabelWidth - 2 * kDragLabelBorderX);

const float kDragLinkLabelFontSize = 11;
const float kDragLinkUrlFontSize = 10;

}  // anonymous namespace

PaintImage DragImage::ResizeAndOrientImage(
    const PaintImage& image,
    ImageOrientation orientation,
    FloatSize image_scale,
    float opacity,
    InterpolationQuality interpolation_quality) {
  IntSize size(image.width(), image.height());
  size.Scale(image_scale.Width(), image_scale.Height());
  AffineTransform transform;
  if (orientation != kDefaultImageOrientation) {
    if (orientation.UsesWidthAsHeight())
      size = size.TransposedSize();
    transform *= orientation.TransformFromDefault(FloatSize(size));
  }
  transform.ScaleNonUniform(image_scale.Width(), image_scale.Height());

  if (size.IsEmpty())
    return PaintImage();

  if (transform.IsIdentity() && opacity == 1) {
    // Nothing to adjust, just use the original.
    DCHECK_EQ(image.width(), size.Width());
    DCHECK_EQ(image.height(), size.Height());
    return image;
  }

  sk_sp<SkSurface> surface =
      SkSurface::MakeRasterN32Premul(size.Width(), size.Height());
  if (!surface)
    return PaintImage();

  SkPaint paint;
  DCHECK_GE(opacity, 0);
  DCHECK_LE(opacity, 1);
  paint.setAlpha(opacity * 255);
  paint.setFilterQuality(interpolation_quality == kInterpolationNone
                             ? kNone_SkFilterQuality
                             : kHigh_SkFilterQuality);

  SkCanvas* canvas = surface->getCanvas();
  std::unique_ptr<SkCanvas> color_transform_canvas;
  color_transform_canvas =
      SkCreateColorSpaceXformCanvas(canvas, SkColorSpace::MakeSRGB());
  canvas = color_transform_canvas.get();
  canvas->concat(AffineTransformToSkMatrix(transform));
  canvas->drawImage(image.GetSkImage(), 0, 0, &paint);

  return PaintImageBuilder::WithProperties(std::move(image))
      .set_image(surface->makeImageSnapshot(), PaintImage::GetNextContentId())
      .TakePaintImage();
}

FloatSize DragImage::ClampedImageScale(const IntSize& image_size,
                                       const IntSize& size,
                                       const IntSize& max_size) {
  // Non-uniform scaling for size mapping.
  FloatSize image_scale(
      static_cast<float>(size.Width()) / image_size.Width(),
      static_cast<float>(size.Height()) / image_size.Height());

  // Uniform scaling for clamping.
  const float clamp_scale_x =
      size.Width() > max_size.Width()
          ? static_cast<float>(max_size.Width()) / size.Width()
          : 1;
  const float clamp_scale_y =
      size.Height() > max_size.Height()
          ? static_cast<float>(max_size.Height()) / size.Height()
          : 1;
  image_scale.Scale(std::min(clamp_scale_x, clamp_scale_y));

  return image_scale;
}

std::unique_ptr<DragImage> DragImage::Create(
    Image* image,
    RespectImageOrientationEnum should_respect_image_orientation,
    float device_scale_factor,
    InterpolationQuality interpolation_quality,
    float opacity,
    FloatSize image_scale) {
  if (!image)
    return nullptr;

  PaintImage paint_image = image->PaintImageForCurrentFrame();
  if (!paint_image)
    return nullptr;

  ImageOrientation orientation;
  if (should_respect_image_orientation == kRespectImageOrientation &&
      image->IsBitmapImage())
    orientation = ToBitmapImage(image)->CurrentFrameOrientation();

  SkBitmap bm;
  paint_image = ResizeAndOrientImage(paint_image, orientation, image_scale,
                                     opacity, interpolation_quality);
  if (!paint_image || !paint_image.GetSkImage()->asLegacyBitmap(&bm))
    return nullptr;

  return base::WrapUnique(
      new DragImage(bm, device_scale_factor, interpolation_quality));
}

static Font DeriveDragLabelFont(int size,
                                FontSelectionValue font_weight,
                                const FontDescription& system_font) {
  FontDescription description = system_font;
  description.SetWeight(font_weight);
  description.SetSpecifiedSize(size);
  description.SetComputedSize(size);
  Font result(description);
  result.Update(nullptr);
  return result;
}

std::unique_ptr<DragImage> DragImage::Create(const KURL& url,
                                             const String& in_label,
                                             const FontDescription& system_font,
                                             float device_scale_factor) {
  const Font label_font = DeriveDragLabelFont(kDragLinkLabelFontSize,
                                              BoldWeightValue(), system_font);
  const SimpleFontData* label_font_data = label_font.PrimaryFont();
  DCHECK(label_font_data);
  const Font url_font = DeriveDragLabelFont(kDragLinkUrlFontSize,
                                            NormalWeightValue(), system_font);
  const SimpleFontData* url_font_data = url_font.PrimaryFont();
  DCHECK(url_font_data);

  if (!label_font_data || !url_font_data)
    return nullptr;

  FontCachePurgePreventer font_cache_purge_preventer;

  bool draw_url_string = true;
  bool clip_url_string = false;
  bool clip_label_string = false;
  float max_drag_label_string_width_dip =
      kMaxDragLabelStringWidth / device_scale_factor;

  String url_string = url.GetString();
  String label = in_label.StripWhiteSpace();
  if (label.IsEmpty()) {
    draw_url_string = false;
    label = url_string;
  }

  // First step is drawing the link drag image width.
  TextRun label_run(label.Impl());
  TextRun url_run(url_string.Impl());
  IntSize label_size(label_font.Width(label_run),
                     label_font_data->GetFontMetrics().Ascent() +
                         label_font_data->GetFontMetrics().Descent());

  if (label_size.Width() > max_drag_label_string_width_dip) {
    label_size.SetWidth(max_drag_label_string_width_dip);
    clip_label_string = true;
  }

  IntSize url_string_size;
  IntSize image_size(label_size.Width() + kDragLabelBorderX * 2,
                     label_size.Height() + kDragLabelBorderY * 2);

  if (draw_url_string) {
    url_string_size.SetWidth(url_font.Width(url_run));
    url_string_size.SetHeight(url_font_data->GetFontMetrics().Ascent() +
                              url_font_data->GetFontMetrics().Descent());
    image_size.SetHeight(image_size.Height() + url_string_size.Height());
    if (url_string_size.Width() > max_drag_label_string_width_dip) {
      image_size.SetWidth(max_drag_label_string_width_dip);
      clip_url_string = true;
    } else {
      image_size.SetWidth(
          std::max(label_size.Width(), url_string_size.Width()) +
          kDragLabelBorderX * 2);
    }
  }

  // We now know how big the image needs to be, so we create and
  // fill the background
  IntSize scaled_image_size = image_size;
  scaled_image_size.Scale(device_scale_factor);
  std::unique_ptr<CanvasResourceProvider> resource_provider(
      CanvasResourceProvider::Create(
          scaled_image_size, CanvasResourceProvider::kSoftwareResourceUsage,
          nullptr,  // context_provider_wrapper
          0,        // msaa_sample_count
          CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
          nullptr));  // canvas_resource_dispatcher
  if (!resource_provider)
    return nullptr;

  resource_provider->Canvas()->scale(device_scale_factor, device_scale_factor);

  const float kDragLabelRadius = 5;

  IntRect rect(IntPoint(), image_size);
  PaintFlags background_paint;
  background_paint.setColor(SkColorSetRGB(140, 140, 140));
  background_paint.setAntiAlias(true);
  SkRRect rrect;
  rrect.setRectXY(SkRect::MakeWH(image_size.Width(), image_size.Height()),
                  kDragLabelRadius, kDragLabelRadius);
  resource_provider->Canvas()->drawRRect(rrect, background_paint);

  // Draw the text
  PaintFlags text_paint;
  if (draw_url_string) {
    if (clip_url_string)
      url_string = StringTruncator::CenterTruncate(
          url_string, image_size.Width() - (kDragLabelBorderX * 2.0f),
          url_font);
    FloatPoint text_pos(
        kDragLabelBorderX,
        image_size.Height() -
            (kLabelBorderYOffset + url_font_data->GetFontMetrics().Descent()));
    TextRun text_run(url_string);
    url_font.DrawText(resource_provider->Canvas(), TextRunPaintInfo(text_run),
                      text_pos, device_scale_factor, text_paint);
  }

  if (clip_label_string)
    label = StringTruncator::RightTruncate(
        label, image_size.Width() - (kDragLabelBorderX * 2.0f), label_font);

  bool has_strong_directionality;
  TextRun text_run =
      TextRunWithDirectionality(label, &has_strong_directionality);
  IntPoint text_pos(
      kDragLabelBorderX,
      kDragLabelBorderY + label_font.GetFontDescription().ComputedPixelSize());
  if (has_strong_directionality &&
      text_run.Direction() == TextDirection::kRtl) {
    float text_width = label_font.Width(text_run);
    int available_width = image_size.Width() - kDragLabelBorderX * 2;
    text_pos.SetX(available_width - ceilf(text_width));
  }
  label_font.DrawBidiText(resource_provider->Canvas(),
                          TextRunPaintInfo(text_run), FloatPoint(text_pos),
                          Font::kDoNotPaintIfFontNotReady, device_scale_factor,
                          text_paint);

  scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
  return DragImage::Create(image.get(), kDoNotRespectImageOrientation,
                           device_scale_factor);
}

DragImage::DragImage(const SkBitmap& bitmap,
                     float resolution_scale,
                     InterpolationQuality interpolation_quality)
    : bitmap_(bitmap),
      resolution_scale_(resolution_scale),
      interpolation_quality_(interpolation_quality) {}

DragImage::~DragImage() = default;

void DragImage::Scale(float scale_x, float scale_y) {
  skia::ImageOperations::ResizeMethod resize_method =
      interpolation_quality_ == kInterpolationNone
          ? skia::ImageOperations::RESIZE_BOX
          : skia::ImageOperations::RESIZE_LANCZOS3;
  int image_width = scale_x * bitmap_.width();
  int image_height = scale_y * bitmap_.height();
  bitmap_ = skia::ImageOperations::Resize(bitmap_, resize_method, image_width,
                                          image_height);
}

}  // namespace blink
