// 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) {}

  virtual void clear(SkColor color) SK_OVERRIDE {}
  virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
    SkBitmap bitmap;
    if (GetBitmapFromPaint(paint, &bitmap)) {
      SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
      AddBitmap(bitmap, clip_rect);
    }
  }

  virtual void drawPoints(const SkDraw& draw,
                          SkCanvas::PointMode mode,
                          size_t count,
                          const SkPoint points[],
                          const SkPaint& paint) SK_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);
  }
  virtual void drawRect(const SkDraw& draw,
                        const SkRect& rect,
                        const SkPaint& paint) SK_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);
    }
  }
  virtual void drawOval(const SkDraw& draw,
                        const SkRect& rect,
                        const SkPaint& paint) SK_OVERRIDE {
    GatherPixelRefDevice::drawRect(draw, rect, paint);
  }
  virtual void drawRRect(const SkDraw& draw,
                         const SkRRect& rect,
                         const SkPaint& paint) SK_OVERRIDE {
    GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
  }
  virtual void drawPath(const SkDraw& draw,
                        const SkPath& path,
                        const SkPaint& paint,
                        const SkMatrix* pre_path_matrix,
                        bool path_is_mutable) SK_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);
  }
  virtual void drawBitmap(const SkDraw& draw,
                          const SkBitmap& bitmap,
                          const SkMatrix& matrix,
                          const SkPaint& paint) SK_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);
  }
  virtual void drawBitmapRect(const SkDraw& draw,
                              const SkBitmap& bitmap,
                              const SkRect* src_or_null,
                              const SkRect& dst,
                              const SkPaint& paint,
                              SkCanvas::DrawBitmapRectFlags flags) SK_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);
  }
  virtual void drawSprite(const SkDraw& draw,
                          const SkBitmap& bitmap,
                          int x,
                          int y,
                          const SkPaint& paint) SK_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);
  }
  virtual void drawText(const SkDraw& draw,
                        const void* text,
                        size_t len,
                        SkScalar x,
                        SkScalar y,
                        const SkPaint& paint) SK_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);
  }
  virtual void drawPosText(const SkDraw& draw,
                           const void* text,
                           size_t len,
                           const SkScalar pos[],
                           SkScalar const_y,
                           int scalars_per_pos,
                           const SkPaint& paint) SK_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 max_point;
    if (scalars_per_pos == 1) {
      min_point.set(pos[0], const_y);
      max_point.set(pos[0], const_y);
    } else if (scalars_per_pos == 2) {
      min_point.set(pos[0], const_y + pos[1]);
      max_point.set(pos[0], const_y + pos[1]);
    }

    for (size_t i = 0; i < len; ++i) {
      SkScalar x = pos[i * scalars_per_pos];
      SkScalar y = const_y;
      if (scalars_per_pos == 2)
        y += pos[i * scalars_per_pos + 1];

      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);
  }
  virtual void drawTextOnPath(const SkDraw& draw,
                              const void* text,
                              size_t len,
                              const SkPath& path,
                              const SkMatrix* matrix,
                              const SkPaint& paint) SK_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);
  }
  virtual 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) SK_OVERRIDE {
    GatherPixelRefDevice::drawPoints(
        draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
  }
  virtual void drawDevice(const SkDraw&,
                          SkBaseDevice*,
                          int x,
                          int y,
                          const SkPaint&) SK_OVERRIDE {}

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

  virtual bool onWritePixels(const SkImageInfo& info,
                             const void* pixels,
                             size_t rowBytes,
                             int x,
                             int y) SK_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
