/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFilterQuality.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

static void setTypeface(SkFont* font, const char name[], SkFontStyle style) {
    font->setTypeface(ToolUtils::create_portable_typeface(name, style));
}

static SkSize computeSize(const SkBitmap& bm, const SkMatrix& mat) {
    SkRect bounds = SkRect::MakeWH(SkIntToScalar(bm.width()),
                                   SkIntToScalar(bm.height()));
    mat.mapRect(&bounds);
    return SkSize::Make(bounds.width(), bounds.height());
}

static void draw_cell(SkCanvas* canvas, const SkBitmap& bm, const SkMatrix& mat, SkScalar dx,
                      SkFilterQuality lvl) {
    SkPaint paint;
    paint.setFilterQuality(lvl);

    SkAutoCanvasRestore acr(canvas, true);
    canvas->translate(dx, 0);
    canvas->concat(mat);
    canvas->drawBitmap(bm, 0, 0, &paint);
}

static void draw_row(SkCanvas* canvas, const SkBitmap& bm, const SkMatrix& mat, SkScalar dx) {
    draw_cell(canvas, bm, mat, 0 * dx, kNone_SkFilterQuality);
    draw_cell(canvas, bm, mat, 1 * dx, kLow_SkFilterQuality);
    draw_cell(canvas, bm, mat, 2 * dx, kMedium_SkFilterQuality);
    draw_cell(canvas, bm, mat, 3 * dx, kHigh_SkFilterQuality);
}

class FilterBitmapGM : public skiagm::GM {
    void onOnceBeforeDraw() override {
        this->setBGColor(0xFFDDDDDD);

        this->makeBitmap();

        SkScalar cx = SkScalarHalf(fBM.width());
        SkScalar cy = SkScalarHalf(fBM.height());
        SkScalar scale = this->getScale();

        // these two matrices use a scale factor configured by the subclass
        fMatrix[0].setScale(scale, scale);
        fMatrix[1].setRotate(30, cx, cy); fMatrix[1].postScale(scale, scale);

        // up/down scaling mix
        fMatrix[2].setScale(0.7f, 1.05f);
    }

protected:
    SkBitmap    fBM;
    SkMatrix    fMatrix[3];

    SkISize onISize() override { return SkISize::Make(1024, 768); }

    virtual void makeBitmap() = 0;
    virtual SkScalar getScale() = 0;

    void onDraw(SkCanvas* canvas) override {

        canvas->translate(10, 10);
        for (size_t i = 0; i < SK_ARRAY_COUNT(fMatrix); ++i) {
            SkSize size = computeSize(fBM, fMatrix[i]);
            size.fWidth += 20;
            size.fHeight += 20;

            draw_row(canvas, fBM, fMatrix[i], size.fWidth);
            canvas->translate(0, size.fHeight);
        }
    }
};

class FilterBitmapTextGM: public FilterBitmapGM {
public:
      FilterBitmapTextGM(float textSize) : fTextSize(textSize) {}

private:
      SkString onShortName() override {
          return SkStringPrintf("filterbitmap_text_%.2fpt", fTextSize);
      }
      const float fTextSize;

      SkScalar getScale() override {
          return 32.f/fTextSize;
      }

      void makeBitmap() override {
          fBM.allocN32Pixels(int(fTextSize * 8), int(fTextSize * 6));
          SkCanvas canvas(fBM);
          canvas.drawColor(SK_ColorWHITE);

          SkPaint paint;
          SkFont font;
          font.setSize(fTextSize);
          font.setSubpixel(true);

          setTypeface(&font, "serif", SkFontStyle::Normal());
          canvas.drawString("Hamburgefons", fTextSize/2, 1.2f*fTextSize, font, paint);
          setTypeface(&font, "serif", SkFontStyle::Bold());
          canvas.drawString("Hamburgefons", fTextSize/2, 2.4f*fTextSize, font, paint);
          setTypeface(&font, "serif", SkFontStyle::Italic());
          canvas.drawString("Hamburgefons", fTextSize/2, 3.6f*fTextSize, font, paint);
          setTypeface(&font, "serif", SkFontStyle::BoldItalic());
          canvas.drawString("Hamburgefons", fTextSize/2, 4.8f*fTextSize, font, paint);
      }
};

class FilterBitmapCheckerboardGM: public FilterBitmapGM {
    SkString onShortName() override {
        return SkStringPrintf("filterbitmap_checkerboard_%d_%d%s",
                              fSize, fNumChecks, fConvertToG8 ? "_g8" : "");
    }
public:
    FilterBitmapCheckerboardGM(int size, int num_checks, bool convertToG8 = false)
        : fSize(size), fNumChecks(num_checks), fConvertToG8(convertToG8) {}

protected:
      int fSize;
      int fNumChecks;

      SkScalar getScale() override {
          return 192.f/fSize;
      }

      void makeBitmap() override {
          fBM.allocN32Pixels(fSize, fSize);
          for (int y = 0; y < fSize; y ++) {
              for (int x = 0; x < fSize; x ++) {
                  SkPMColor* s = fBM.getAddr32(x, y);
                  int cx = (x * fNumChecks) / fSize;
                  int cy = (y * fNumChecks) / fSize;
                  if ((cx+cy)%2) {
                      *s = 0xFFFFFFFF;
                  } else {
                      *s = 0xFF000000;
                  }
              }
          }
          if (fConvertToG8) {
              SkBitmap tmp;
              ToolUtils::copy_to_g8(&tmp, fBM);
              fBM = tmp;
          }
      }
private:
    const bool fConvertToG8;
    typedef FilterBitmapGM INHERITED;
};

class FilterBitmapImageGM: public FilterBitmapGM {
    const char* fFilename;
    int fSize;

    SkString onShortName() override {
        return SkStringPrintf("filterbitmap_image_%s%s", fFilename, fConvertToG8 ? "_g8" : "");
    }

public:
    FilterBitmapImageGM(const char filename[], bool convertToG8 = false)
        : fFilename(filename), fConvertToG8(convertToG8) {}

protected:
      SkScalar getScale() override {
          return 192.f/fSize;
      }

      void makeBitmap() override {
        SkString resource = SkStringPrintf("images/%s", fFilename);
        if (!GetResourceAsBitmap(resource.c_str(), &fBM)) {
            fBM.allocN32Pixels(1, 1);
            fBM.eraseARGB(255, 255, 0 , 0); // red == bad
        }
        fSize = fBM.height();

        if (fConvertToG8) {
            SkBitmap tmp;
            ToolUtils::copy_to_g8(&tmp, fBM);
            fBM = tmp;
        }
      }
private:
    const bool fConvertToG8;
    typedef FilterBitmapGM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM( return new FilterBitmapTextGM(3); )
DEF_GM( return new FilterBitmapTextGM(7); )
DEF_GM( return new FilterBitmapTextGM(10); )
DEF_GM( return new FilterBitmapCheckerboardGM(4,4); )
DEF_GM( return new FilterBitmapCheckerboardGM(32,32); )
DEF_GM( return new FilterBitmapCheckerboardGM(32,32, true); )
DEF_GM( return new FilterBitmapCheckerboardGM(32,8); )
DEF_GM( return new FilterBitmapCheckerboardGM(32,2); )
DEF_GM( return new FilterBitmapCheckerboardGM(192,192); )
DEF_GM( return new FilterBitmapImageGM("mandrill_16.png"); )
DEF_GM( return new FilterBitmapImageGM("mandrill_32.png"); )
DEF_GM( return new FilterBitmapImageGM("mandrill_64.png"); )
DEF_GM( return new FilterBitmapImageGM("mandrill_64.png", true); )
DEF_GM( return new FilterBitmapImageGM("mandrill_128.png"); )
DEF_GM( return new FilterBitmapImageGM("mandrill_256.png"); )
DEF_GM( return new FilterBitmapImageGM("mandrill_512.png"); )
DEF_GM( return new FilterBitmapImageGM("color_wheel.png"); )
