summaryrefslogtreecommitdiff
path: root/animator/SkDrawExtraPathEffect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'animator/SkDrawExtraPathEffect.cpp')
-rw-r--r--animator/SkDrawExtraPathEffect.cpp515
1 files changed, 515 insertions, 0 deletions
diff --git a/animator/SkDrawExtraPathEffect.cpp b/animator/SkDrawExtraPathEffect.cpp
new file mode 100644
index 00000000..e973dbf7
--- /dev/null
+++ b/animator/SkDrawExtraPathEffect.cpp
@@ -0,0 +1,515 @@
+
+/*
+ * 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 "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 addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
+ 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 addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
+ 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) {
+ }
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT()
+
+protected:
+ virtual SkScalar begin(SkScalar contourLength) const {
+ SkScriptValue value;
+ SkAnimatorScript engine(*fMaker, NULL, 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(SkPath* dst, SkScalar distance, SkPathMeasure&) const {
+ fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance);
+ SkDrawPath* drawPath = NULL;
+ 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;
+ m.reset();
+ 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();
+ }
+ if (matrix) {
+ m = matrix->getMatrix();
+ }
+ }
+ SkScalar result = 0;
+ SkAnimatorScript::EvaluateFloat(*fMaker, NULL, 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(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
+}
+
+SkDrawShapePathEffect::~SkDrawShapePathEffect() {
+ SkSafeUnref(fPathEffect);
+}
+
+bool SkDrawShapePathEffect::addChild(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 == NULL || (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 SkIRect& uvBounds, SkPath*) const SK_OVERRIDE {
+ const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
+ }
+
+ virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE {
+ const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
+ }
+
+private:
+ void setUVBounds(const SkIRect& uvBounds) {
+ fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
+ SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
+ }
+
+ void addPath(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 == NULL)
+ 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);
+ }
+
+ 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;
+ int32_t fU;
+ int32_t 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 == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
+ matrix == NULL)
+ 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(NULL), effect2(NULL) {
+}
+
+SkDrawComposePathEffect::~SkDrawComposePathEffect() {
+ delete effect1;
+ delete effect2;
+}
+
+bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
+ if (effect1 == NULL)
+ 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() :
+ skDrawShape1DPathEffectType(SkType_Unknown),
+ skDrawShape2DPathEffectType(SkType_Unknown),
+ skDrawComposePathEffectType(SkType_Unknown),
+ skDrawCornerPathEffectType(SkType_Unknown) {
+ }
+
+ virtual SkDisplayable* createInstance(SkDisplayTypes type) {
+ SkDisplayable* result = NULL;
+ 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 = NULL;
+ 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 = NULL;
+ 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());
+}
+
+////////////////
+
+
+SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
+}