
/*
 * 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 "SampleCode.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkView.h"
#include "SkLayer.h"

#include "SkMatrix44.h"
static void test_inv(const char label[], const SkMatrix44& mat) {
    SkDebugf("%s\n", label);
    mat.dump();

    SkMatrix44 inv;
    if (mat.invert(&inv)) {
        inv.dump();
    } else {
        SkDebugf("--- invert failed\n");
    }

    SkMatrix44 a, b;
    a.setConcat(mat, inv);
    b.setConcat(inv, mat);
    SkDebugf("concat mat with inverse pre=%d post=%d\n", a.isIdentity(), b.isIdentity());
    if (!a.isIdentity()) {
        a.dump();
    }
    if (!b.isIdentity()) {
        b.dump();
    }
    SkDebugf("\n");
}

static void test_map(SkScalar x0, SkScalar y0, SkScalar z0,
                     const SkMatrix44& mat,
                     SkScalar x1, SkScalar y1, SkScalar z1) {
    SkVector4 src, dst;
    src.set(x0, y0, z0);
    dst = mat * src;
    SkDebugf("map: src: %g %g %g dst: %g %g %g (%g) expected: %g %g %g match: %d\n",
             x0, y0, z0,
             dst.fData[0], dst.fData[1], dst.fData[2], dst.fData[3],
             x1, y1, z1,
             dst.fData[0] == x1 && dst.fData[1] == y1 && dst.fData[2] == z1);
}

static void test_33(const SkMatrix44& mat,
                    SkScalar x0, SkScalar x1, SkScalar x2,
                    SkScalar y0, SkScalar y1, SkScalar y2) {
    SkMatrix dst = mat;
    if (dst[0] != x0 || dst[1] != x1 || dst[2] != x2 ||
        dst[3] != y0 || dst[4] != y1 || dst[5] != y2) {
        SkString str;
        dst.toDumpString(&str);
        SkDebugf("3x3: expected 3x3 [%g %g %g] [%g %g %g] bug got %s\n",
                 x0, x1, x2, y0, y1, y2, str.c_str());
    }
}

static void test44() {
    SkMatrix44 m0, m1, m2;

    test_inv("identity", m0);
    m0.setTranslate(2,3,4);
    test_inv("translate", m0);
    m0.setScale(2,3,4);
    test_inv("scale", m0);
    m0.postTranslate(5, 6, 7);
    test_inv("postTranslate", m0);
    m0.setScale(2,3,4);
    m1.setTranslate(5, 6, 7);
    m0.setConcat(m0, m1);
    test_inv("postTranslate2", m0);
    m0.setScale(2,3,4);
    m0.preTranslate(5, 6, 7);
    test_inv("preTranslate", m0);
    
    m0.setScale(2, 4, 6);
    m0.postScale(SkDoubleToMScalar(0.5));
    test_inv("scale/postscale to 1,2,3", m0);

    m0.reset();
    test_map(1, 0, 0, m0, 1, 0, 0);
    test_map(0, 1, 0, m0, 0, 1, 0);
    test_map(0, 0, 1, m0, 0, 0, 1);
    m0.setScale(2, 3, 4);
    test_map(1, 0, 0, m0, 2, 0, 0);
    test_map(0, 1, 0, m0, 0, 3, 0);
    test_map(0, 0, 1, m0, 0, 0, 4);
    m0.setTranslate(2, 3, 4);
    test_map(0, 0, 0, m0, 2, 3, 4);
    m0.preScale(5, 6, 7);
    test_map(1, 0, 0, m0, 7, 3, 4);
    test_map(0, 1, 0, m0, 2, 9, 4);
    test_map(0, 0, 1, m0, 2, 3, 11);

    SkMScalar deg = 45;
    m0.setRotateDegreesAbout(0, 0, 1, deg);
    test_map(1, 0, 0, m0, 0.707106769, -0.707106769, 0);

    m0.reset();
    test_33(m0, 1, 0, 0, 0, 1, 0);
    m0.setTranslate(3, 4, 5);
    test_33(m0, 1, 0, 3, 0, 1, 4);
}
    
///////////////////////////////////////////////////////////////////////////////

static void dump_layers(const SkLayer* layer, int tab = 0) {
    SkMatrix matrix;
    SkString matrixStr;

    layer->getLocalTransform(&matrix);
    matrix.toDumpString(&matrixStr);

    for (int j = 0; j < tab; j++) {
        SkDebugf(" ");
    }
    SkDebugf("layer=%p parent=%p size=[%g %g] transform=%s\n",
             layer, layer->getParent(), layer->getWidth(), layer->getHeight(),
             matrixStr.c_str());
    for (int i = 0; i < layer->countChildren(); i++) {
        dump_layers(layer->getChild(i), tab + 4);
    }
}

class TestLayer : public SkLayer {
public:
    TestLayer(SkColor c) : fColor(c) {}

protected:
    virtual void onDraw(SkCanvas* canvas, SkScalar opacity) {
        SkRect r;
        r.set(0, 0, this->getWidth(), this->getHeight());

        SkPaint paint;
        paint.setColor(fColor);
        paint.setAlpha(SkScalarRound(opacity * 255));

        canvas->drawRect(r, paint);
    }

private:
    SkColor fColor;
};

class SkLayerView : public SkView {
private:
    SkLayer* fRootLayer;
    SkLayer* fLastChild;
public:
	SkLayerView() {
        test44();
        static const int W = 600;
        static const int H = 440;
        static const struct {
            int fWidth;
            int fHeight;
            SkColor fColor;
            int fPosX;
            int fPosY;
        } gData[] = {
            { 120, 80, SK_ColorRED, 0, 0 },
            { 120, 80, SK_ColorGREEN, W - 120, 0 },
            { 120, 80, SK_ColorBLUE, 0, H - 80 },
            { 120, 80, SK_ColorMAGENTA, W - 120, H - 80 },
        };

        fRootLayer = new TestLayer(0xFFDDDDDD);
        fRootLayer->setSize(W, H);
        for (size_t i = 0; i < SK_ARRAY_COUNT(gData); i++) {
            SkLayer* child = new TestLayer(gData[i].fColor);
            child->setSize(gData[i].fWidth, gData[i].fHeight);
            child->setPosition(gData[i].fPosX, gData[i].fPosY);
            fRootLayer->addChild(child)->unref();
        }
        
        SkLayer* child = new TestLayer(0xFFDD8844);
        child->setSize(120, 80);
        child->setPosition(fRootLayer->getWidth()/2 - child->getWidth()/2,
                           fRootLayer->getHeight()/2 - child->getHeight()/2);
        child->setAnchorPoint(SK_ScalarHalf, SK_ScalarHalf);
        {
            SkMatrix m;
            m.setRotate(SkIntToScalar(30));
            child->setMatrix(m);
        }
        fLastChild = child;
        fRootLayer->addChild(child)->unref();
        
        if (false) {
            SkMatrix matrix;
            matrix.setScale(0.5, 0.5);
            fRootLayer->setMatrix(matrix);
        }

//        dump_layers(fRootLayer);
    }
    
    virtual ~SkLayerView() {
        SkSafeUnref(fRootLayer);
    }
    
protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "SkLayer");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    
    virtual void onDraw(SkCanvas* canvas) {
        canvas->drawColor(SK_ColorWHITE);
        
        canvas->translate(20, 20);
        fRootLayer->draw(canvas);
        
        // visual test of getLocalTransform
        if (true) {
            SkMatrix matrix;
            fLastChild->localToGlobal(&matrix);
            SkPaint paint;
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setStrokeWidth(5);
            paint.setColor(0x88FF0000);
            canvas->concat(matrix);
            canvas->drawRect(SkRect::MakeSize(fLastChild->getSize()), paint);
        }
    }
    
private:
    typedef SkView INHERITED;
};

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

static SkView* MyFactory() { return new SkLayerView; }
static SkViewRegister reg(MyFactory);

