michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkDrawMatrix.h" michael@0: #include "SkAnimateMaker.h" michael@0: #include "SkCanvas.h" michael@0: #include "SkPaint.h" michael@0: #include "SkParse.h" michael@0: #include "SkMatrixParts.h" michael@0: #include "SkScript.h" michael@0: #include "SkTypedArray.h" michael@0: michael@0: enum SkDrawMatrix_Properties { michael@0: SK_PROPERTY(perspectX), michael@0: SK_PROPERTY(perspectY), michael@0: SK_PROPERTY(rotate), michael@0: SK_PROPERTY(scale), michael@0: SK_PROPERTY(scaleX), michael@0: SK_PROPERTY(scaleY), michael@0: SK_PROPERTY(skewX), michael@0: SK_PROPERTY(skewY), michael@0: SK_PROPERTY(translate), michael@0: SK_PROPERTY(translateX), michael@0: SK_PROPERTY(translateY) michael@0: }; michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawMatrix::fInfo[] = { michael@0: SK_MEMBER_ARRAY(matrix, Float), michael@0: SK_MEMBER_PROPERTY(perspectX, Float), michael@0: SK_MEMBER_PROPERTY(perspectY, Float), michael@0: SK_MEMBER_PROPERTY(rotate, Float), michael@0: SK_MEMBER_PROPERTY(scale, Float), michael@0: SK_MEMBER_PROPERTY(scaleX, Float), michael@0: SK_MEMBER_PROPERTY(scaleY, Float), michael@0: SK_MEMBER_PROPERTY(skewX, Float), michael@0: SK_MEMBER_PROPERTY(skewY, Float), michael@0: SK_MEMBER_PROPERTY(translate, Point), michael@0: SK_MEMBER_PROPERTY(translateX, Float), michael@0: SK_MEMBER_PROPERTY(translateY, Float) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawMatrix); michael@0: michael@0: SkDrawMatrix::SkDrawMatrix() : fChildHasID(false), fDirty(false) { michael@0: fConcat.reset(); michael@0: fMatrix.reset(); michael@0: } michael@0: michael@0: SkDrawMatrix::~SkDrawMatrix() { michael@0: for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) michael@0: delete *part; michael@0: } michael@0: michael@0: bool SkDrawMatrix::addChild(SkAnimateMaker& maker, SkDisplayable* child) { michael@0: SkASSERT(child && child->isMatrixPart()); michael@0: SkMatrixPart* part = (SkMatrixPart*) child; michael@0: *fParts.append() = part; michael@0: if (part->add()) michael@0: maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToMatrix); michael@0: return true; michael@0: } michael@0: michael@0: bool SkDrawMatrix::childrenNeedDisposing() const { michael@0: return false; michael@0: } michael@0: michael@0: SkDisplayable* SkDrawMatrix::deepCopy(SkAnimateMaker* maker) { michael@0: SkDrawMatrix* copy = (SkDrawMatrix*) michael@0: SkDisplayType::CreateInstance(maker, SkType_Matrix); michael@0: SkASSERT(fParts.count() == 0); michael@0: copy->fMatrix = fMatrix; michael@0: copy->fConcat = fConcat; michael@0: return copy; michael@0: } michael@0: michael@0: void SkDrawMatrix::dirty() { michael@0: fDirty = true; michael@0: } michael@0: michael@0: bool SkDrawMatrix::draw(SkAnimateMaker& maker) { michael@0: SkMatrix& concat = getMatrix(); michael@0: maker.fCanvas->concat(concat); michael@0: return false; michael@0: } michael@0: michael@0: #ifdef SK_DUMP_ENABLED michael@0: void SkDrawMatrix::dump(SkAnimateMaker* maker) { michael@0: dumpBase(maker); michael@0: if (fMatrix.isIdentity()) { michael@0: SkDebugf("matrix=\"identity\"/>\n"); michael@0: return; michael@0: } michael@0: SkScalar result; michael@0: result = fMatrix[SkMatrix::kMScaleX]; michael@0: if (result != SK_Scalar1) michael@0: SkDebugf("sx=\"%g\" ", SkScalarToFloat(result)); michael@0: result = fMatrix.getScaleY(); michael@0: if (result != SK_Scalar1) michael@0: SkDebugf("sy=\"%g\" ", SkScalarToFloat(result)); michael@0: result = fMatrix.getSkewX(); michael@0: if (result) michael@0: SkDebugf("skew-x=\"%g\" ", SkScalarToFloat(result)); michael@0: result = fMatrix.getSkewY(); michael@0: if (result) michael@0: SkDebugf("skew-y=\"%g\" ", SkScalarToFloat(result)); michael@0: result = fMatrix.getTranslateX(); michael@0: if (result) michael@0: SkDebugf("tx=\"%g\" ", SkScalarToFloat(result)); michael@0: result = fMatrix.getTranslateY(); michael@0: if (result) michael@0: SkDebugf("ty=\"%g\" ", SkScalarToFloat(result)); michael@0: result = SkPerspToScalar(fMatrix.getPerspX()); michael@0: if (result) michael@0: SkDebugf("perspect-x=\"%g\" ", SkScalarToFloat(result)); michael@0: result = SkPerspToScalar(fMatrix.getPerspY()); michael@0: if (result) michael@0: SkDebugf("perspect-y=\"%g\" ", SkScalarToFloat(result)); michael@0: SkDebugf("/>\n"); michael@0: } michael@0: #endif michael@0: michael@0: SkMatrix& SkDrawMatrix::getMatrix() { michael@0: if (fDirty == false) michael@0: return fConcat; michael@0: fMatrix.reset(); michael@0: for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) { michael@0: (*part)->add(); michael@0: fConcat = fMatrix; michael@0: } michael@0: fDirty = false; michael@0: return fConcat; michael@0: } michael@0: michael@0: bool SkDrawMatrix::getProperty(int index, SkScriptValue* value) const { michael@0: value->fType = SkType_Float; michael@0: SkScalar result; michael@0: switch (index) { michael@0: case SK_PROPERTY(perspectX): michael@0: result = fMatrix.getPerspX(); michael@0: break; michael@0: case SK_PROPERTY(perspectY): michael@0: result = fMatrix.getPerspY(); michael@0: break; michael@0: case SK_PROPERTY(scaleX): michael@0: result = fMatrix.getScaleX(); michael@0: break; michael@0: case SK_PROPERTY(scaleY): michael@0: result = fMatrix.getScaleY(); michael@0: break; michael@0: case SK_PROPERTY(skewX): michael@0: result = fMatrix.getSkewX(); michael@0: break; michael@0: case SK_PROPERTY(skewY): michael@0: result = fMatrix.getSkewY(); michael@0: break; michael@0: case SK_PROPERTY(translateX): michael@0: result = fMatrix.getTranslateX(); michael@0: break; michael@0: case SK_PROPERTY(translateY): michael@0: result = fMatrix.getTranslateY(); michael@0: break; michael@0: default: michael@0: // SkASSERT(0); michael@0: return false; michael@0: } michael@0: value->fOperand.fScalar = result; michael@0: return true; michael@0: } michael@0: michael@0: void SkDrawMatrix::initialize() { michael@0: fConcat = fMatrix; michael@0: } michael@0: michael@0: void SkDrawMatrix::onEndElement(SkAnimateMaker& ) { michael@0: if (matrix.count() > 0) { michael@0: SkScalar* vals = matrix.begin(); michael@0: fMatrix.setScaleX(vals[0]); michael@0: fMatrix.setSkewX(vals[1]); michael@0: fMatrix.setTranslateX(vals[2]); michael@0: fMatrix.setSkewY(vals[3]); michael@0: fMatrix.setScaleY(vals[4]); michael@0: fMatrix.setTranslateY(vals[5]); michael@0: fMatrix.setPerspX(SkScalarToPersp(vals[6])); michael@0: fMatrix.setPerspY(SkScalarToPersp(vals[7])); michael@0: // fMatrix.setPerspW(SkScalarToPersp(vals[8])); michael@0: goto setConcat; michael@0: } michael@0: if (fChildHasID == false) { michael@0: { michael@0: for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) michael@0: delete *part; michael@0: } michael@0: fParts.reset(); michael@0: setConcat: michael@0: fConcat = fMatrix; michael@0: fDirty = false; michael@0: } michael@0: } michael@0: michael@0: void SkDrawMatrix::setChildHasID() { michael@0: fChildHasID = true; michael@0: } michael@0: michael@0: bool SkDrawMatrix::setProperty(int index, SkScriptValue& scriptValue) { michael@0: SkScalar number = scriptValue.fOperand.fScalar; michael@0: switch (index) { michael@0: case SK_PROPERTY(translate): michael@0: // SkScalar xy[2]; michael@0: SkASSERT(scriptValue.fType == SkType_Array); michael@0: SkASSERT(scriptValue.fOperand.fArray->getType() == SkType_Float); michael@0: SkASSERT(scriptValue.fOperand.fArray->count() == 2); michael@0: // SkParse::FindScalars(scriptValue.fOperand.fString->c_str(), xy, 2); michael@0: fMatrix.setTranslateX((*scriptValue.fOperand.fArray)[0].fScalar); michael@0: fMatrix.setTranslateY((*scriptValue.fOperand.fArray)[1].fScalar); michael@0: return true; michael@0: case SK_PROPERTY(perspectX): michael@0: fMatrix.setPerspX(SkScalarToPersp((number))); michael@0: break; michael@0: case SK_PROPERTY(perspectY): michael@0: fMatrix.setPerspY(SkScalarToPersp((number))); michael@0: break; michael@0: case SK_PROPERTY(rotate): { michael@0: SkMatrix temp; michael@0: temp.setRotate(number, 0, 0); michael@0: fMatrix.setScaleX(temp.getScaleX()); michael@0: fMatrix.setScaleY(temp.getScaleY()); michael@0: fMatrix.setSkewX(temp.getSkewX()); michael@0: fMatrix.setSkewY(temp.getSkewY()); michael@0: } break; michael@0: case SK_PROPERTY(scale): michael@0: fMatrix.setScaleX(number); michael@0: fMatrix.setScaleY(number); michael@0: break; michael@0: case SK_PROPERTY(scaleX): michael@0: fMatrix.setScaleX(number); michael@0: break; michael@0: case SK_PROPERTY(scaleY): michael@0: fMatrix.setScaleY(number); michael@0: break; michael@0: case SK_PROPERTY(skewX): michael@0: fMatrix.setSkewX(number); michael@0: break; michael@0: case SK_PROPERTY(skewY): michael@0: fMatrix.setSkewY(number); michael@0: break; michael@0: case SK_PROPERTY(translateX): michael@0: fMatrix.setTranslateX(number); michael@0: break; michael@0: case SK_PROPERTY(translateY): michael@0: fMatrix.setTranslateY(number); michael@0: break; michael@0: default: michael@0: SkASSERT(0); michael@0: return false; michael@0: } michael@0: fConcat = fMatrix; michael@0: return true; michael@0: }