/*
 * 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.h"

namespace skiagm {

/** Create a bitmap image suitable for testing SkBitmap::scrollRect().
 *
 *  @param quarterWidth bitmap will be 4x this many pixels wide
 *  @param quarterHeight bitmap will be 4x this many pixels tall
 *  @param bitmap the bitmap data is written into this object
 */
static void make_bitmap(int quarterWidth, int quarterHeight, SkBitmap *bitmap) {
    SkPaint pRed, pWhite, pGreen, pBlue, pLine, pAlphaGray;
    pRed.setColor(0xFFFF9999);
    pWhite.setColor(0xFFFFFFFF);
    pGreen.setColor(0xFF99FF99);
    pBlue.setColor(0xFF9999FF);
    pLine.setColor(0xFF000000);
    pLine.setStyle(SkPaint::kStroke_Style);
    pAlphaGray.setColor(0x66888888);

    // Prepare bitmap, and a canvas that draws into it.
    bitmap->reset();
    bitmap->setConfig(SkBitmap::kARGB_8888_Config,
                      quarterWidth*4, quarterHeight*4);
    bitmap->allocPixels();
    SkCanvas canvas(*bitmap);

    SkScalar w = SkIntToScalar(quarterWidth);
    SkScalar h = SkIntToScalar(quarterHeight);
    canvas.drawRectCoords(  0,   0, w*2, h*2, pRed);
    canvas.drawRectCoords(w*2,   0, w*4, h*2, pGreen);
    canvas.drawRectCoords(  0, h*2, w*2, h*4, pBlue);
    canvas.drawRectCoords(w*2, h*2, w*4, h*4, pWhite);
    canvas.drawRectCoords(w, h, w*3, h*3, pAlphaGray);
    canvas.drawLine(w*2,   0, w*2, h*4, pLine);
    canvas.drawLine(  0, h*2, w*4, h*2, pLine);
    canvas.drawRectCoords(w, h, w*3, h*3, pLine);
}

class BitmapScrollGM : public GM {
    bool fInited;
    void init() {
        if (fInited) {
            return;
        }
        fInited = true;
        // Create the original bitmap.
        make_bitmap(quarterWidth, quarterHeight, &origBitmap);
    }

public:
    BitmapScrollGM() {
        fInited = false;
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    virtual SkString onShortName() {
        return SkString("bitmapscroll");
    }

    virtual SkISize onISize() {
      return make_isize(800, 600);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->init();
        SkIRect scrollCenterRegion = SkIRect::MakeXYWH(
            quarterWidth, quarterHeight, quarterWidth*2+1, quarterHeight*2+1);
        int x = quarterWidth;
        int y = quarterHeight;
        int xSpacing = quarterWidth * 20;
        int ySpacing = quarterHeight * 16;

        // Draw left-hand text labels.
        drawLabel(canvas, "scroll entire bitmap",
                  x, y, x, y + ySpacing);
        drawLabel(canvas, "scroll part of bitmap",
                  x, y + ySpacing, x, y + ySpacing*2);
        x += 30;

        // Draw various permutations of scrolled bitmaps, scrolling a bit
        // further each time.
        draw9(canvas, x, y, NULL, quarterWidth*1/2, quarterHeight*1/2);
        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
              quarterWidth*1/2, quarterHeight*1/2);
        x += xSpacing;
        draw9(canvas, x, y, NULL, quarterWidth*3/2, quarterHeight*3/2);
        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
              quarterWidth*3/2, quarterHeight*3/2);
        x += xSpacing;
        draw9(canvas, x, y, NULL, quarterWidth*5/2, quarterHeight*5/2);
        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
              quarterWidth*5/2, quarterHeight*5/2);
        x += xSpacing;
        draw9(canvas, x, y, NULL, quarterWidth*9/2, quarterHeight*9/2);
        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
              quarterWidth*9/2, quarterHeight*9/2);
    }

    void drawLabel(SkCanvas* canvas, const char *text, int startX, int startY,
                 int endX, int endY) {
        SkPaint paint;
        paint.setColor(0xFF000000);
        SkPath path;
        path.moveTo(SkIntToScalar(startX), SkIntToScalar(startY));
        path.lineTo(SkIntToScalar(endX), SkIntToScalar(endY));
        canvas->drawTextOnPath(text, strlen(text), path, NULL, paint);
    }

    /** Stamp out 9 copies of origBitmap, scrolled in each direction (and
     *  not scrolled at all).
     */
    void draw9(SkCanvas* canvas, int x, int y, SkIRect* subset,
               int scrollX, int scrollY) {
        for (int yMult=-1; yMult<=1; yMult++) {
            for (int xMult=-1; xMult<=1; xMult++) {
                // Figure out the (x,y) to draw this copy at
                SkScalar bitmapX = SkIntToScalar(
                    x + quarterWidth * 5 * (xMult+1));
                SkScalar bitmapY = SkIntToScalar(
                    y + quarterHeight * 5 * (yMult+1));

                // Scroll a new copy of the bitmap, and then draw it.
                // scrollRect() should always return true, even if it's a no-op
                SkBitmap scrolledBitmap;
                SkDEBUGCODE(bool copyToReturnValue = )origBitmap.copyTo(
                    &scrolledBitmap, origBitmap.config());
                SkASSERT(copyToReturnValue);
                SkDEBUGCODE(bool scrollRectReturnValue = )scrolledBitmap.scrollRect(
                    subset, scrollX * xMult, scrollY * yMult);
                SkASSERT(scrollRectReturnValue);
                canvas->drawBitmap(scrolledBitmap, bitmapX, bitmapY);
            }
        }
    }

private:
    typedef GM INHERITED;
    static const int quarterWidth = 10;
    static const int quarterHeight = 14;
    SkBitmap origBitmap;
};

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

static GM* MyFactory(void*) { return new BitmapScrollGM; }
static GMRegistry reg(MyFactory);

}