/*
* 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 = SkPerspToScalar(fMatrix.getPerspX());
if (result)
SkDebugf("perspect-x=\"%g\" ", SkScalarToFloat(result));
result = SkPerspToScalar(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(SkScalarToPersp(vals[6]));
fMatrix.setPerspY(SkScalarToPersp(vals[7]));
// fMatrix.setPerspW(SkScalarToPersp(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(SkScalarToPersp((number)));
break;
case SK_PROPERTY(perspectY):
fMatrix.setPerspY(SkScalarToPersp((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;
}