// 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) {
    // 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;
      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 clear(SkColor color) override {}
  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);
    }
  }

  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);
      mapped_rect.intersect(SkRect::Make(draw.fRC->getBounds()));
      AddBitmap(bitmap, mapped_rect);
    }
  }
  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);

    SkBitmap paint_bitmap;
    if (GetBitmapFromPaint(paint, &paint_bitmap))
      AddBitmap(paint_bitmap, mapped_rect);
  }
  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);

    AddBitmap(bitmap, mapped_rect);
    SkBitmap paint_bitmap;
    if (GetBitmapFromPaint(paint, &paint_bitmap))
      AddBitmap(paint_bitmap, mapped_rect);
  }
  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) {
    SkRect canvas_rect = SkRect::MakeWH(width(), height());
    SkRect paint_rect = SkRect::MakeEmpty();
    paint_rect.intersect(rect, canvas_rect);
    pixel_ref_set_->Add(bm.pixelRef(), paint_rect);
  }

  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);

  SkBitmap empty_bitmap;
  empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture->width(), picture->height()));

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

  canvas.clipRect(SkRect::MakeWH(picture->width(), picture->height()),
                  SkRegion::kIntersect_Op,
                  false);
  canvas.drawPicture(picture);
}

}  // namespace skia
