
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkDrawMatrix.h"
#include "SkAnimateMaker.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkParse.h"
#include "SkMatrixParts.h"
#include "SkScript.h"
#include "SkTypedArray.h"

enum SkDrawMatrix_Properties {
    SK_PROPERTY(perspectX),
    SK_PROPERTY(perspectY),
    SK_PROPERTY(rotate),
    SK_PROPERTY(scale),
    SK_PROPERTY(scaleX),
    SK_PROPERTY(scaleY),
    SK_PROPERTY(skewX),
    SK_PROPERTY(skewY),
    SK_PROPERTY(translate),
    SK_PROPERTY(translateX),
    SK_PROPERTY(translateY)
};

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkDrawMatrix::fInfo[] = {
    SK_MEMBER_ARRAY(matrix, Float),
    SK_MEMBER_PROPERTY(perspectX, Float),
    SK_MEMBER_PROPERTY(perspectY, Float),
    SK_MEMBER_PROPERTY(rotate, Float),
    SK_MEMBER_PROPERTY(scale, Float),
    SK_MEMBER_PROPERTY(scaleX, Float),
    SK_MEMBER_PROPERTY(scaleY, Float),
    SK_MEMBER_PROPERTY(skewX, Float),
    SK_MEMBER_PROPERTY(skewY, Float),
    SK_MEMBER_PROPERTY(translate, Point),
    SK_MEMBER_PROPERTY(translateX, Float),
    SK_MEMBER_PROPERTY(translateY, Float)
};

#endif

DEFINE_GET_MEMBER(SkDrawMatrix);

SkDrawMatrix::SkDrawMatrix() : fChildHasID(false), fDirty(false) {
    fConcat.reset();
    fMatrix.reset();
}

SkDrawMatrix::~SkDrawMatrix() {
    for (SkMatrixPart** part = fParts.begin(); part < fParts.end();  part++)
        delete *part;
}

bool SkDrawMatrix::addChild(SkAnimateMaker& maker, SkDisplayable* child) {
    SkASSERT(child && child->isMatrixPart());
    SkMatrixPart* part = (SkMatrixPart*) child;
    *fParts.append() = part;
    if (part->add())
        maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToMatrix);
    return true;
}

bool SkDrawMatrix::childrenNeedDisposing() const {
    return false;
}

SkDisplayable* SkDrawMatrix::deepCopy(SkAnimateMaker* maker) {
    SkDrawMatrix* copy = (SkDrawMatrix*)
        SkDisplayType::CreateInstance(maker, SkType_Matrix);
    SkASSERT(fParts.count() == 0);
    copy->fMatrix = fMatrix;
    copy->fConcat = fConcat;
    return copy;
}

void SkDrawMatrix::dirty() {
    fDirty = true;
}

bool SkDrawMatrix::draw(SkAnimateMaker& maker) {
    SkMatrix& concat = getMatrix();
    maker.fCanvas->concat(concat);
    return false;
}

#ifdef SK_DUMP_ENABLED
void SkDrawMatrix::dump(SkAnimateMaker* maker) {
    dumpBase(maker);
    if (fMatrix.isIdentity()) {
        SkDebugf("matrix=\"identity\"/>\n");
        return;
    }
    SkScalar result;
    result = fMatrix[SkMatrix::kMScaleX];
    if (result != SK_Scalar1)
        SkDebugf("sx=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getScaleY();
    if (result != SK_Scalar1)
        SkDebugf("sy=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getSkewX();
    if (result)
        SkDebugf("skew-x=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getSkewY();
    if (result)
        SkDebugf("skew-y=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getTranslateX();
    if (result)
        SkDebugf("tx=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getTranslateY();
    if (result)
        SkDebugf("ty=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getPerspX();
    if (result)
        SkDebugf("perspect-x=\"%g\" ", SkScalarToFloat(result));
    result = fMatrix.getPerspY();
    if (result)
        SkDebugf("perspect-y=\"%g\" ", SkScalarToFloat(result));
    SkDebugf("/>\n");
}
#endif

SkMatrix& SkDrawMatrix::getMatrix() {
    if (fDirty == false)
        return fConcat;
    fMatrix.reset();
    for (SkMatrixPart** part = fParts.begin(); part < fParts.end();  part++) {
        (*part)->add();
        fConcat = fMatrix;
    }
    fDirty = false;
    return fConcat;
}

bool SkDrawMatrix::getProperty(int index, SkScriptValue* value) const {
    value->fType = SkType_Float;
    SkScalar result;
    switch (index) {
        case SK_PROPERTY(perspectX):
            result = fMatrix.getPerspX();
            break;
        case SK_PROPERTY(perspectY):
            result = fMatrix.getPerspY();
            break;
        case SK_PROPERTY(scaleX):
            result = fMatrix.getScaleX();
            break;
        case SK_PROPERTY(scaleY):
            result = fMatrix.getScaleY();
            break;
        case SK_PROPERTY(skewX):
            result = fMatrix.getSkewX();
            break;
        case SK_PROPERTY(skewY):
            result = fMatrix.getSkewY();
            break;
        case SK_PROPERTY(translateX):
            result = fMatrix.getTranslateX();
            break;
        case SK_PROPERTY(translateY):
            result = fMatrix.getTranslateY();
            break;
        default:
//          SkASSERT(0);
            return false;
    }
    value->fOperand.fScalar = result;
    return true;
}

void SkDrawMatrix::initialize() {
    fConcat = fMatrix;
}

void SkDrawMatrix::onEndElement(SkAnimateMaker& ) {
    if (matrix.count() > 0) {
        SkScalar* vals = matrix.begin();
        fMatrix.setScaleX(vals[0]);
        fMatrix.setSkewX(vals[1]);
        fMatrix.setTranslateX(vals[2]);
        fMatrix.setSkewY(vals[3]);
        fMatrix.setScaleY(vals[4]);
        fMatrix.setTranslateY(vals[5]);
        fMatrix.setPerspX(vals[6]);
        fMatrix.setPerspY(vals[7]);
//      fMatrix.setPerspW(vals[8]);
        goto setConcat;
    }
    if (fChildHasID == false) {
        {
            for (SkMatrixPart** part = fParts.begin(); part < fParts.end();  part++)
                delete *part;
        }
        fParts.reset();
setConcat:
        fConcat = fMatrix;
        fDirty = false;
    }
}

void SkDrawMatrix::setChildHasID() {
    fChildHasID = true;
}

bool SkDrawMatrix::setProperty(int index, SkScriptValue& scriptValue) {
    SkScalar number = scriptValue.fOperand.fScalar;
    switch (index) {
        case SK_PROPERTY(translate):
    //      SkScalar xy[2];
            SkASSERT(scriptValue.fType == SkType_Array);
            SkASSERT(scriptValue.fOperand.fArray->getType() == SkType_Float);
            SkASSERT(scriptValue.fOperand.fArray->count() == 2);
    //      SkParse::FindScalars(scriptValue.fOperand.fString->c_str(), xy, 2);
            fMatrix.setTranslateX((*scriptValue.fOperand.fArray)[0].fScalar);
            fMatrix.setTranslateY((*scriptValue.fOperand.fArray)[1].fScalar);
            return true;
        case SK_PROPERTY(perspectX):
            fMatrix.setPerspX(number);
            break;
        case SK_PROPERTY(perspectY):
            fMatrix.setPerspY(number);
            break;
        case SK_PROPERTY(rotate): {
            SkMatrix temp;
            temp.setRotate(number, 0, 0);
            fMatrix.setScaleX(temp.getScaleX());
            fMatrix.setScaleY(temp.getScaleY());
            fMatrix.setSkewX(temp.getSkewX());
            fMatrix.setSkewY(temp.getSkewY());
            } break;
        case SK_PROPERTY(scale):
            fMatrix.setScaleX(number);
            fMatrix.setScaleY(number);
            break;
        case SK_PROPERTY(scaleX):
            fMatrix.setScaleX(number);
            break;
        case SK_PROPERTY(scaleY):
            fMatrix.setScaleY(number);
            break;
        case SK_PROPERTY(skewX):
            fMatrix.setSkewX(number);
            break;
        case SK_PROPERTY(skewY):
            fMatrix.setSkewY(number);
            break;
        case SK_PROPERTY(translateX):
            fMatrix.setTranslateX(number);
            break;
        case SK_PROPERTY(translateY):
            fMatrix.setTranslateY(number);
            break;
        default:
            SkASSERT(0);
            return false;
    }
    fConcat = fMatrix;
    return true;
}
