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