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 "SkDrawExtraPathEffect.h" michael@0: #include "SkDrawPath.h" michael@0: #include "Sk1DPathEffect.h" michael@0: #include "Sk2DPathEffect.h" michael@0: #include "SkMemberInfo.h" michael@0: #include "SkPaintParts.h" michael@0: #include "SkPathEffect.h" michael@0: #include "SkCornerPathEffect.h" michael@0: michael@0: #include "SkDashPathEffect.h" michael@0: michael@0: class SkDrawShapePathEffect : public SkDrawPathEffect { michael@0: DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect); michael@0: SkDrawShapePathEffect(); michael@0: virtual ~SkDrawShapePathEffect(); michael@0: virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE; michael@0: virtual SkPathEffect* getPathEffect(); michael@0: protected: michael@0: SkDrawable* addPath; michael@0: SkDrawable* addMatrix; michael@0: SkDrawPath* path; michael@0: SkPathEffect* fPathEffect; michael@0: friend class SkShape1DPathEffect; michael@0: friend class SkShape2DPathEffect; michael@0: }; michael@0: michael@0: class SkDrawShape1DPathEffect : public SkDrawShapePathEffect { michael@0: DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect); michael@0: SkDrawShape1DPathEffect(SkDisplayTypes ); michael@0: virtual ~SkDrawShape1DPathEffect(); michael@0: virtual void onEndElement(SkAnimateMaker& ); michael@0: private: michael@0: SkString phase; michael@0: SkString spacing; michael@0: friend class SkShape1DPathEffect; michael@0: typedef SkDrawShapePathEffect INHERITED; michael@0: }; michael@0: michael@0: class SkDrawShape2DPathEffect : public SkDrawShapePathEffect { michael@0: DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect); michael@0: SkDrawShape2DPathEffect(SkDisplayTypes ); michael@0: virtual ~SkDrawShape2DPathEffect(); michael@0: virtual void onEndElement(SkAnimateMaker& ); michael@0: private: michael@0: SkDrawMatrix* matrix; michael@0: friend class SkShape2DPathEffect; michael@0: typedef SkDrawShapePathEffect INHERITED; michael@0: }; michael@0: michael@0: class SkDrawComposePathEffect : public SkDrawPathEffect { michael@0: DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect); michael@0: SkDrawComposePathEffect(SkDisplayTypes ); michael@0: virtual ~SkDrawComposePathEffect(); michael@0: virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE; michael@0: virtual SkPathEffect* getPathEffect(); michael@0: virtual bool isPaint() const; michael@0: private: michael@0: SkDrawPathEffect* effect1; michael@0: SkDrawPathEffect* effect2; michael@0: }; michael@0: michael@0: class SkDrawCornerPathEffect : public SkDrawPathEffect { michael@0: DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect); michael@0: SkDrawCornerPathEffect(SkDisplayTypes ); michael@0: virtual ~SkDrawCornerPathEffect(); michael@0: virtual SkPathEffect* getPathEffect(); michael@0: private: michael@0: SkScalar radius; michael@0: }; michael@0: michael@0: //////////// SkShape1DPathEffect michael@0: michael@0: #include "SkAnimateMaker.h" michael@0: #include "SkAnimatorScript.h" michael@0: #include "SkDisplayApply.h" michael@0: #include "SkDrawMatrix.h" michael@0: #include "SkPaint.h" michael@0: michael@0: class SkShape1DPathEffect : public Sk1DPathEffect { michael@0: public: michael@0: SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) : michael@0: fDraw(draw), fMaker(maker) { michael@0: } michael@0: michael@0: SK_DECLARE_UNFLATTENABLE_OBJECT() michael@0: michael@0: protected: michael@0: virtual SkScalar begin(SkScalar contourLength) const { michael@0: SkScriptValue value; michael@0: SkAnimatorScript engine(*fMaker, NULL, SkType_Float); michael@0: engine.propertyCallBack(GetContourLength, &contourLength); michael@0: value.fOperand.fScalar = 0; michael@0: engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float); michael@0: return value.fOperand.fScalar; michael@0: } michael@0: michael@0: virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const { michael@0: fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance); michael@0: SkDrawPath* drawPath = NULL; michael@0: if (fDraw->addPath->isPath()) { michael@0: drawPath = (SkDrawPath*) fDraw->addPath; michael@0: } else { michael@0: SkApply* apply = (SkApply*) fDraw->addPath; michael@0: apply->refresh(*fMaker); michael@0: apply->activate(*fMaker); michael@0: apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000)); michael@0: drawPath = (SkDrawPath*) apply->getScope(); michael@0: } michael@0: SkMatrix m; michael@0: m.reset(); michael@0: if (fDraw->addMatrix) { michael@0: SkDrawMatrix* matrix; michael@0: if (fDraw->addMatrix->getType() == SkType_Matrix) michael@0: matrix = (SkDrawMatrix*) fDraw->addMatrix; michael@0: else { michael@0: SkApply* apply = (SkApply*) fDraw->addMatrix; michael@0: apply->refresh(*fMaker); michael@0: apply->activate(*fMaker); michael@0: apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000)); michael@0: matrix = (SkDrawMatrix*) apply->getScope(); michael@0: } michael@0: if (matrix) { michael@0: m = matrix->getMatrix(); michael@0: } michael@0: } michael@0: SkScalar result = 0; michael@0: SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result); michael@0: if (drawPath) michael@0: dst->addPath(drawPath->getPath(), m); michael@0: fMaker->clearExtraPropertyCallBack(fDraw->fType); michael@0: return result; michael@0: } michael@0: michael@0: private: michael@0: static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) { michael@0: if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) { michael@0: value->fOperand.fScalar = *(SkScalar*) clen; michael@0: value->fType = SkType_Float; michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) { michael@0: if (SK_LITERAL_STR_EQUAL("distance", token, len)) { michael@0: value->fOperand.fScalar = *(SkScalar*) dist; michael@0: value->fType = SkType_Float; michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: SkDrawShape1DPathEffect* fDraw; michael@0: SkAnimateMaker* fMaker; michael@0: }; michael@0: michael@0: //////////// SkDrawShapePathEffect michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawShapePathEffect::fInfo[] = { michael@0: SK_MEMBER(addMatrix, Drawable), // either matrix or apply michael@0: SK_MEMBER(addPath, Drawable), // either path or apply michael@0: SK_MEMBER(path, Path), michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawShapePathEffect); michael@0: michael@0: SkDrawShapePathEffect::SkDrawShapePathEffect() : michael@0: addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) { michael@0: } michael@0: michael@0: SkDrawShapePathEffect::~SkDrawShapePathEffect() { michael@0: SkSafeUnref(fPathEffect); michael@0: } michael@0: michael@0: bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) { michael@0: path = (SkDrawPath*) child; michael@0: return true; michael@0: } michael@0: michael@0: SkPathEffect* SkDrawShapePathEffect::getPathEffect() { michael@0: fPathEffect->ref(); michael@0: return fPathEffect; michael@0: } michael@0: michael@0: //////////// SkDrawShape1DPathEffect michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = { michael@0: SK_MEMBER_INHERITED, michael@0: SK_MEMBER(phase, String), michael@0: SK_MEMBER(spacing, String), michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawShape1DPathEffect); michael@0: michael@0: SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) { michael@0: } michael@0: michael@0: SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() { michael@0: } michael@0: michael@0: void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) { michael@0: if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false)) michael@0: maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error michael@0: else michael@0: fPathEffect = new SkShape1DPathEffect(this, &maker); michael@0: } michael@0: michael@0: ////////// SkShape2DPathEffect michael@0: michael@0: class SkShape2DPathEffect : public Sk2DPathEffect { michael@0: public: michael@0: SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker, michael@0: const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) { michael@0: } michael@0: michael@0: protected: michael@0: virtual void begin(const SkIRect& uvBounds, SkPath*) const SK_OVERRIDE { michael@0: const_cast(this)->setUVBounds(uvBounds); michael@0: } michael@0: michael@0: virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE { michael@0: const_cast(this)->addPath(loc, u, v, dst); michael@0: } michael@0: michael@0: private: michael@0: void setUVBounds(const SkIRect& uvBounds) { michael@0: fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop), michael@0: SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom)); michael@0: } michael@0: michael@0: void addPath(const SkPoint& loc, int u, int v, SkPath* dst) { michael@0: fLoc = loc; michael@0: fU = u; michael@0: fV = v; michael@0: SkDrawPath* drawPath; michael@0: fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this); michael@0: if (fDraw->addPath->isPath()) { michael@0: drawPath = (SkDrawPath*) fDraw->addPath; michael@0: } else { michael@0: SkApply* apply = (SkApply*) fDraw->addPath; michael@0: apply->refresh(*fMaker); michael@0: apply->activate(*fMaker); michael@0: apply->interpolate(*fMaker, v); michael@0: drawPath = (SkDrawPath*) apply->getScope(); michael@0: } michael@0: if (drawPath == NULL) michael@0: goto clearCallBack; michael@0: if (fDraw->matrix) { michael@0: SkDrawMatrix* matrix; michael@0: if (fDraw->matrix->getType() == SkType_Matrix) michael@0: matrix = (SkDrawMatrix*) fDraw->matrix; michael@0: else { michael@0: SkApply* apply = (SkApply*) fDraw->matrix; michael@0: apply->activate(*fMaker); michael@0: apply->interpolate(*fMaker, v); michael@0: matrix = (SkDrawMatrix*) apply->getScope(); michael@0: } michael@0: if (matrix) { michael@0: dst->addPath(drawPath->getPath(), matrix->getMatrix()); michael@0: goto clearCallBack; michael@0: } michael@0: } michael@0: dst->addPath(drawPath->getPath()); michael@0: clearCallBack: michael@0: fMaker->clearExtraPropertyCallBack(fDraw->fType); michael@0: } michael@0: michael@0: static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) { michael@0: static const char match[] = "locX|locY|left|top|right|bottom|u|v" ; michael@0: SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D; michael@0: int index; michael@0: if (SkAnimatorScript::MapEnums(match, token, len, &index) == false) michael@0: return false; michael@0: SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6); michael@0: if (index < 6) { michael@0: value->fType = SkType_Float; michael@0: value->fOperand.fScalar = (&shape2D->fLoc.fX)[index]; michael@0: } else { michael@0: value->fType = SkType_Int; michael@0: value->fOperand.fS32 = (&shape2D->fU)[index - 6]; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: SkPoint fLoc; michael@0: SkRect fUVBounds; michael@0: int32_t fU; michael@0: int32_t fV; michael@0: SkDrawShape2DPathEffect* fDraw; michael@0: SkAnimateMaker* fMaker; michael@0: michael@0: // illegal michael@0: SkShape2DPathEffect(const SkShape2DPathEffect&); michael@0: SkShape2DPathEffect& operator=(const SkShape2DPathEffect&); michael@0: }; michael@0: michael@0: ////////// SkDrawShape2DPathEffect michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = { michael@0: SK_MEMBER_INHERITED, michael@0: SK_MEMBER(matrix, Matrix) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawShape2DPathEffect); michael@0: michael@0: SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) { michael@0: } michael@0: michael@0: SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() { michael@0: } michael@0: michael@0: void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) { michael@0: if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) || michael@0: matrix == NULL) michael@0: maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error michael@0: else michael@0: fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix()); michael@0: } michael@0: michael@0: ////////// SkDrawComposePathEffect michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawComposePathEffect::fInfo[] = { michael@0: SK_MEMBER(effect1, PathEffect), michael@0: SK_MEMBER(effect2, PathEffect) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawComposePathEffect); michael@0: michael@0: SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type), michael@0: effect1(NULL), effect2(NULL) { michael@0: } michael@0: michael@0: SkDrawComposePathEffect::~SkDrawComposePathEffect() { michael@0: delete effect1; michael@0: delete effect2; michael@0: } michael@0: michael@0: bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) { michael@0: if (effect1 == NULL) michael@0: effect1 = (SkDrawPathEffect*) child; michael@0: else michael@0: effect2 = (SkDrawPathEffect*) child; michael@0: return true; michael@0: } michael@0: michael@0: SkPathEffect* SkDrawComposePathEffect::getPathEffect() { michael@0: SkPathEffect* e1 = effect1->getPathEffect(); michael@0: SkPathEffect* e2 = effect2->getPathEffect(); michael@0: SkPathEffect* composite = SkComposePathEffect::Create(e1, e2); michael@0: e1->unref(); michael@0: e2->unref(); michael@0: return composite; michael@0: } michael@0: michael@0: bool SkDrawComposePathEffect::isPaint() const { michael@0: return true; michael@0: } michael@0: michael@0: //////////// SkDrawCornerPathEffect michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = { michael@0: SK_MEMBER(radius, Float) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawCornerPathEffect); michael@0: michael@0: SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type): michael@0: fType(type), radius(0) { michael@0: } michael@0: michael@0: SkDrawCornerPathEffect::~SkDrawCornerPathEffect() { michael@0: } michael@0: michael@0: SkPathEffect* SkDrawCornerPathEffect::getPathEffect() { michael@0: return SkCornerPathEffect::Create(radius); michael@0: } michael@0: michael@0: ///////// michael@0: michael@0: #include "SkExtras.h" michael@0: michael@0: const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D"; michael@0: const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D"; michael@0: const char kDrawComposePathEffectName[] = "pathEffect:compose"; michael@0: const char kDrawCornerPathEffectName[] = "pathEffect:corner"; michael@0: michael@0: class SkExtraPathEffects : public SkExtras { michael@0: public: michael@0: SkExtraPathEffects() : michael@0: skDrawShape1DPathEffectType(SkType_Unknown), michael@0: skDrawShape2DPathEffectType(SkType_Unknown), michael@0: skDrawComposePathEffectType(SkType_Unknown), michael@0: skDrawCornerPathEffectType(SkType_Unknown) { michael@0: } michael@0: michael@0: virtual SkDisplayable* createInstance(SkDisplayTypes type) { michael@0: SkDisplayable* result = NULL; michael@0: if (skDrawShape1DPathEffectType == type) michael@0: result = new SkDrawShape1DPathEffect(type); michael@0: else if (skDrawShape2DPathEffectType == type) michael@0: result = new SkDrawShape2DPathEffect(type); michael@0: else if (skDrawComposePathEffectType == type) michael@0: result = new SkDrawComposePathEffect(type); michael@0: else if (skDrawCornerPathEffectType == type) michael@0: result = new SkDrawCornerPathEffect(type); michael@0: return result; michael@0: } michael@0: michael@0: virtual bool definesType(SkDisplayTypes type) { michael@0: return type == skDrawShape1DPathEffectType || michael@0: type == skDrawShape2DPathEffectType || michael@0: type == skDrawComposePathEffectType || michael@0: type == skDrawCornerPathEffectType; michael@0: } michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) { michael@0: const SkMemberInfo* info = NULL; michael@0: int infoCount = 0; michael@0: if (skDrawShape1DPathEffectType == type) { michael@0: info = SkDrawShape1DPathEffect::fInfo; michael@0: infoCount = SkDrawShape1DPathEffect::fInfoCount; michael@0: } else if (skDrawShape2DPathEffectType == type) { michael@0: info = SkDrawShape2DPathEffect::fInfo; michael@0: infoCount = SkDrawShape2DPathEffect::fInfoCount; michael@0: } else if (skDrawComposePathEffectType == type) { michael@0: info = SkDrawComposePathEffect::fInfo; michael@0: infoCount = SkDrawShape1DPathEffect::fInfoCount; michael@0: } else if (skDrawCornerPathEffectType == type) { michael@0: info = SkDrawCornerPathEffect::fInfo; michael@0: infoCount = SkDrawCornerPathEffect::fInfoCount; michael@0: } michael@0: if (infoCountPtr) michael@0: *infoCountPtr = infoCount; michael@0: return info; michael@0: } michael@0: #endif michael@0: michael@0: #ifdef SK_DEBUG michael@0: virtual const char* getName(SkDisplayTypes type) { michael@0: if (skDrawShape1DPathEffectType == type) michael@0: return kDrawShape1DPathEffectName; michael@0: else if (skDrawShape2DPathEffectType == type) michael@0: return kDrawShape2DPathEffectName; michael@0: else if (skDrawComposePathEffectType == type) michael@0: return kDrawComposePathEffectName; michael@0: else if (skDrawCornerPathEffectType == type) michael@0: return kDrawCornerPathEffectName; michael@0: return NULL; michael@0: } michael@0: #endif michael@0: michael@0: virtual SkDisplayTypes getType(const char name[], size_t len ) { michael@0: SkDisplayTypes* type = NULL; michael@0: if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len)) michael@0: type = &skDrawShape1DPathEffectType; michael@0: else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len)) michael@0: type = &skDrawShape2DPathEffectType; michael@0: else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len)) michael@0: type = &skDrawComposePathEffectType; michael@0: else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len)) michael@0: type = &skDrawCornerPathEffectType; michael@0: if (type) { michael@0: if (*type == SkType_Unknown) michael@0: *type = SkDisplayType::RegisterNewType(); michael@0: return *type; michael@0: } michael@0: return SkType_Unknown; michael@0: } michael@0: michael@0: private: michael@0: SkDisplayTypes skDrawShape1DPathEffectType; michael@0: SkDisplayTypes skDrawShape2DPathEffectType; michael@0: SkDisplayTypes skDrawComposePathEffectType; michael@0: SkDisplayTypes skDrawCornerPathEffectType; michael@0: }; michael@0: michael@0: void InitializeSkExtraPathEffects(SkAnimator* animator) { michael@0: animator->addExtras(new SkExtraPathEffects()); michael@0: } michael@0: michael@0: //////////////// michael@0: michael@0: michael@0: SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) { michael@0: }