// 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 "skia/ext/pixel_ref_utils.h"

#include <algorithm>

#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkDraw.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/utils/SkNoSaveLayerCanvas.h"
#include "third_party/skia/src/core/SkRasterClip.h"

namespace skia {

namespace {

// URI label for a discardable SkPixelRef.
const char kLabelDiscardable[] = "discardable";

class DiscardablePixelRefSet {
 public:
  DiscardablePixelRefSet(
      std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs)
      : pixel_refs_(pixel_refs) {}

  void Add(SkPixelRef* pixel_ref,
           const SkRect& rect,
           const SkMatrix& matrix,
           SkFilterQuality filter_quality) {
    // Only save discardable pixel refs.
    if (pixel_ref->getURI() &&
        !strcmp(pixel_ref->getURI(), kLabelDiscardable)) {
      PixelRefUtils::PositionPixelRef position_pixel_ref;
      position_pixel_ref.pixel_ref = pixel_ref;
      position_pixel_ref.pixel_ref_rect = rect;
      position_pixel_ref.matrix = matrix;
      position_pixel_ref.filter_quality = filter_quality;
      pixel_refs_->push_back(position_pixel_ref);
    }
  }

 private:
  std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs_;
};

class GatherPixelRefDevice : public SkBitmapDevice {
 public:
  GatherPixelRefDevice(const SkBitmap& bm,
                       DiscardablePixelRefSet* pixel_ref_set)
      : SkBitmapDevice(bm), pixel_ref_set_(pixel_ref_set) {}

  void drawPaint(const SkDraw& draw, const SkPaint& paint) override {
    SkBitmap bitmap;
    if (GetBitmapFromPaint(paint, &bitmap)) {
      SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
      AddBitmap(bitmap, clip_rect, *draw.fMatrix, paint.getFilterQuality());
    }
  }

  void drawPoints(const SkDraw& draw,
                  SkCanvas::PointMode mode,
                  size_t count,
                  const SkPoint points[],
                  const SkPaint& paint) override {
    SkBitmap bitmap;
    if (!GetBitmapFromPaint(paint, &bitmap))
      return;

    if (count == 0)
      return;

    SkPoint min_point = points[0];
    SkPoint max_point = points[0];
    for (size_t i = 1; i < count; ++i) {
      const SkPoint& point = points[i];
      min_point.set(std::min(min_point.x(), point.x()),
                    std::min(min_point.y(), point.y()));
      max_point.set(std::max(max_point.x(), point.x()),
                    std::max(max_point.y(), point.y()));
    }

    SkRect bounds = SkRect::MakeLTRB(
        min_point.x(), min_point.y(), max_point.x(), max_point.y());

    GatherPixelRefDevice::drawRect(draw, bounds, paint);
  }
  void drawRect(const SkDraw& draw,
                const SkRect& rect,
                const SkPaint& paint) override {
    SkBitmap bitmap;
    if (GetBitmapFromPaint(paint, &bitmap)) {
      SkRect mapped_rect;
      draw.fMatrix->mapRect(&mapped_rect, rect);
      if (mapped_rect.intersect(SkRect::Make(draw.fRC->getBounds()))) {
        AddBitmap(bitmap, mapped_rect, *draw.fMatrix, paint.getFilterQuality());
      }
    }
  }
  void drawOval(const SkDraw& draw,
                const SkRect& rect,
                const SkPaint& paint) override {
    GatherPixelRefDevice::drawRect(draw, rect, paint);
  }
  void drawRRect(const SkDraw& draw,
                 const SkRRect& rect,
                 const SkPaint& paint) override {
    GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
  }
  void drawPath(const SkDraw& draw,
                const SkPath& path,
                const SkPaint& paint,
                const SkMatrix* pre_path_matrix,
                bool path_is_mutable) override {
    SkBitmap bitmap;
    if (!GetBitmapFromPaint(paint, &bitmap))
      return;

    SkRect path_bounds = path.getBounds();
    SkRect final_rect;
    if (pre_path_matrix != NULL)
      pre_path_matrix->mapRect(&final_rect, path_bounds);
    else
      final_rect = path_bounds;

    GatherPixelRefDevice::drawRect(draw, final_rect, paint);
  }
  void drawBitmap(const SkDraw& draw,
                  const SkBitmap& bitmap,
                  const SkMatrix& matrix,
                  const SkPaint& paint) override {
    SkMatrix total_matrix;
    total_matrix.setConcat(*draw.fMatrix, matrix);

    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
    SkRect mapped_rect;
    total_matrix.mapRect(&mapped_rect, bitmap_rect);
    AddBitmap(bitmap, mapped_rect, total_matrix, paint.getFilterQuality());

    SkBitmap paint_bitmap;
    if (GetBitmapFromPaint(paint, &paint_bitmap)) {
      AddBitmap(paint_bitmap, mapped_rect, total_matrix,
                paint.getFilterQuality());
    }
  }
  void drawBitmapRect(const SkDraw& draw,
                      const SkBitmap& bitmap,
                      const SkRect* src_or_null,
                      const SkRect& dst,
                      const SkPaint& paint,
                      SkCanvas::DrawBitmapRectFlags flags) override {
    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
    SkMatrix matrix;
    matrix.setRectToRect(bitmap_rect, dst, SkMatrix::kFill_ScaleToFit);
    GatherPixelRefDevice::drawBitmap(draw, bitmap, matrix, paint);
  }
  void drawSprite(const SkDraw& draw,
                  const SkBitmap& bitmap,
                  int x,
                  int y,
                  const SkPaint& paint) override {
    // Sprites aren't affected by current matrix, so we can't reuse drawRect.
    SkMatrix matrix;
    matrix.setTranslate(x, y);

    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
    SkRect mapped_rect;
    matrix.mapRect(&mapped_rect, bitmap_rect);

    SkMatrix identity;
    identity.setIdentity();
    // Sprites aren't affected by current matrix, so use the identity matrix.
    AddBitmap(bitmap, mapped_rect, identity, paint.getFilterQuality());
    SkBitmap paint_bitmap;
    if (GetBitmapFromPaint(paint, &paint_bitmap))
      AddBitmap(paint_bitmap, mapped_rect, identity, paint.getFilterQuality());
  }
  void drawText(const SkDraw& draw,
                const void* text,
                size_t len,
                SkScalar x,
                SkScalar y,
                const SkPaint& paint) override {
    SkBitmap bitmap;
    if (!GetBitmapFromPaint(paint, &bitmap))
      return;

    // Math is borrowed from SkBBoxRecord
    SkRect bounds;
    paint.measureText(text, len, &bounds);
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    if (paint.isVerticalText()) {
      SkScalar h = bounds.fBottom - bounds.fTop;
      if (paint.getTextAlign() == SkPaint::kCenter_Align) {
        bounds.fTop -= h / 2;
        bounds.fBottom -= h / 2;
      }
      bounds.fBottom += metrics.fBottom;
      bounds.fTop += metrics.fTop;
    } else {
      SkScalar w = bounds.fRight - bounds.fLeft;
      if (paint.getTextAlign() == SkPaint::kCenter_Align) {
        bounds.fLeft -= w / 2;
        bounds.fRight -= w / 2;
      } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
        bounds.fLeft -= w;
        bounds.fRight -= w;
      }
      bounds.fTop = metrics.fTop;
      bounds.fBottom = metrics.fBottom;
    }

    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
    bounds.fLeft -= pad;
    bounds.fRight += pad;
    bounds.fLeft += x;
    bounds.fRight += x;
    bounds.fTop += y;
    bounds.fBottom += y;

    GatherPixelRefDevice::drawRect(draw, bounds, paint);
  }
  void drawPosText(const SkDraw& draw,
                   const void* text,
                   size_t len,
                   const SkScalar pos[],
                   int scalars_per_pos,
                   const SkPoint& offset,
                   const SkPaint& paint) override {
    SkBitmap bitmap;
    if (!GetBitmapFromPaint(paint, &bitmap))
      return;

    if (len == 0)
      return;

    // Similar to SkDraw asserts.
    SkASSERT(scalars_per_pos == 1 || scalars_per_pos == 2);

    SkPoint min_point = SkPoint::Make(offset.x() + pos[0],
                                      offset.y() + (2 == scalars_per_pos ? pos[1] : 0));
    SkPoint max_point = min_point;

    for (size_t i = 0; i < len; ++i) {
      SkScalar x = offset.x() + pos[i * scalars_per_pos];
      SkScalar y = offset.y() + (2 == scalars_per_pos ? pos[i * scalars_per_pos + 1] : 0);

      min_point.set(std::min(x, min_point.x()), std::min(y, min_point.y()));
      max_point.set(std::max(x, max_point.x()), std::max(y, max_point.y()));
    }

    SkRect bounds = SkRect::MakeLTRB(
        min_point.x(), min_point.y(), max_point.x(), max_point.y());

    // Math is borrowed from SkBBoxRecord
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    bounds.fTop += metrics.fTop;
    bounds.fBottom += metrics.fBottom;

    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
    bounds.fLeft += pad;
    bounds.fRight -= pad;

    GatherPixelRefDevice::drawRect(draw, bounds, paint);
  }
  void drawTextOnPath(const SkDraw& draw,
                      const void* text,
                      size_t len,
                      const SkPath& path,
                      const SkMatrix* matrix,
                      const SkPaint& paint) override {
    SkBitmap bitmap;
    if (!GetBitmapFromPaint(paint, &bitmap))
      return;

    // Math is borrowed from SkBBoxRecord
    SkRect bounds = path.getBounds();
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);

    SkScalar pad = metrics.fTop;
    bounds.fLeft += pad;
    bounds.fRight -= pad;
    bounds.fTop += pad;
    bounds.fBottom -= pad;

    GatherPixelRefDevice::drawRect(draw, bounds, paint);
  }
  void drawVertices(const SkDraw& draw,
                    SkCanvas::VertexMode,
                    int vertex_count,
                    const SkPoint verts[],
                    const SkPoint texs[],
                    const SkColor colors[],
                    SkXfermode* xmode,
                    const uint16_t indices[],
                    int index_count,
                    const SkPaint& paint) override {
    GatherPixelRefDevice::drawPoints(
        draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
  }
  void drawDevice(const SkDraw&,
                  SkBaseDevice*,
                  int x,
                  int y,
                  const SkPaint&) override {}

 protected:
  bool onReadPixels(const SkImageInfo& info,
                    void* pixels,
                    size_t rowBytes,
                    int x,
                    int y) override {
    return false;
  }

  bool onWritePixels(const SkImageInfo& info,
                     const void* pixels,
                     size_t rowBytes,
                     int x,
                     int y) override {
    return false;
  }

 private:
  DiscardablePixelRefSet* pixel_ref_set_;

  void AddBitmap(const SkBitmap& bm,
                 const SkRect& rect,
                 const SkMatrix& matrix,
                 SkFilterQuality filter_quality) {
    SkRect canvas_rect = SkRect::MakeWH(width(), height());
    SkRect paint_rect = SkRect::MakeEmpty();
    if (paint_rect.intersect(rect, canvas_rect)) {
      pixel_ref_set_->Add(bm.pixelRef(), paint_rect, matrix,
                          filter_quality);
    }
  }

  bool GetBitmapFromPaint(const SkPaint& paint, SkBitmap* bm) {
    SkShader* shader = paint.getShader();
    if (shader) {
      // Check whether the shader is a gradient in order to prevent generation
      // of bitmaps from gradient shaders, which implement asABitmap.
      if (SkShader::kNone_GradientType == shader->asAGradient(NULL))
        return shader->asABitmap(bm, NULL, NULL);
    }
    return false;
  }
};

}  // namespace

void PixelRefUtils::GatherDiscardablePixelRefs(
    SkPicture* picture,
    std::vector<PositionPixelRef>* pixel_refs) {
  pixel_refs->clear();
  DiscardablePixelRefSet pixel_ref_set(pixel_refs);

  SkRect picture_bounds = picture->cullRect();
  SkIRect picture_ibounds = picture_bounds.roundOut();
  SkBitmap empty_bitmap;
  empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture_ibounds.width(),
                                                picture_ibounds.height()));

  GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set);
  SkNoSaveLayerCanvas canvas(&device);

  // Draw the picture pinned against our top/left corner.
  canvas.translate(-picture_bounds.left(), -picture_bounds.top());
  canvas.drawPicture(picture);
}

}  // namespace skia
