Home | History | Annotate | Download | only in animator
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkDrawExtraPathEffect.h"
      9 #include "SkDrawPath.h"
     10 #include "Sk1DPathEffect.h"
     11 #include "Sk2DPathEffect.h"
     12 #include "SkMemberInfo.h"
     13 #include "SkPaintPart.h"
     14 #include "SkPathEffect.h"
     15 #include "SkCornerPathEffect.h"
     16 
     17 #include "SkDashPathEffect.h"
     18 
     19 class SkDrawShapePathEffect : public SkDrawPathEffect {
     20     DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
     21     SkDrawShapePathEffect();
     22     virtual ~SkDrawShapePathEffect();
     23     virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
     24     virtual SkPathEffect* getPathEffect();
     25 protected:
     26     SkDrawable* addPath;
     27     SkDrawable* addMatrix;
     28     SkDrawPath* path;
     29     SkPathEffect* fPathEffect;
     30     friend class SkShape1DPathEffect;
     31     friend class SkShape2DPathEffect;
     32 };
     33 
     34 class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
     35     DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
     36     SkDrawShape1DPathEffect(SkDisplayTypes );
     37     virtual ~SkDrawShape1DPathEffect();
     38     virtual void onEndElement(SkAnimateMaker& );
     39 private:
     40     SkString phase;
     41     SkString spacing;
     42     friend class SkShape1DPathEffect;
     43     typedef SkDrawShapePathEffect INHERITED;
     44 };
     45 
     46 class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
     47     DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
     48     SkDrawShape2DPathEffect(SkDisplayTypes );
     49     virtual ~SkDrawShape2DPathEffect();
     50     virtual void onEndElement(SkAnimateMaker& );
     51 private:
     52     SkDrawMatrix* matrix;
     53     friend class SkShape2DPathEffect;
     54     typedef SkDrawShapePathEffect INHERITED;
     55 };
     56 
     57 class SkDrawComposePathEffect : public SkDrawPathEffect {
     58     DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect);
     59     SkDrawComposePathEffect(SkDisplayTypes );
     60     virtual ~SkDrawComposePathEffect();
     61     virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
     62     virtual SkPathEffect* getPathEffect();
     63     virtual bool isPaint() const;
     64 private:
     65     SkDrawPathEffect* effect1;
     66     SkDrawPathEffect* effect2;
     67 };
     68 
     69 class SkDrawCornerPathEffect : public SkDrawPathEffect {
     70     DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
     71     SkDrawCornerPathEffect(SkDisplayTypes );
     72     virtual ~SkDrawCornerPathEffect();
     73     virtual SkPathEffect* getPathEffect();
     74 private:
     75     SkScalar radius;
     76 };
     77 
     78 //////////// SkShape1DPathEffect
     79 
     80 #include "SkAnimateMaker.h"
     81 #include "SkAnimatorScript.h"
     82 #include "SkDisplayApply.h"
     83 #include "SkDrawMatrix.h"
     84 #include "SkPaint.h"
     85 
     86 class SkShape1DPathEffect : public Sk1DPathEffect {
     87 public:
     88     SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
     89         fDraw(draw), fMaker(maker) {
     90     }
     91 
     92     SK_DECLARE_UNFLATTENABLE_OBJECT()
     93 
     94 protected:
     95     virtual SkScalar begin(SkScalar contourLength) const {
     96         SkScriptValue value;
     97         SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
     98         engine.propertyCallBack(GetContourLength, &contourLength);
     99         value.fOperand.fScalar = 0;
    100         engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float);
    101         return value.fOperand.fScalar;
    102     }
    103 
    104     virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const {
    105         fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance);
    106         SkDrawPath* drawPath = NULL;
    107         if (fDraw->addPath->isPath()) {
    108             drawPath = (SkDrawPath*) fDraw->addPath;
    109         } else {
    110             SkApply* apply = (SkApply*) fDraw->addPath;
    111             apply->refresh(*fMaker);
    112             apply->activate(*fMaker);
    113             apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
    114             drawPath = (SkDrawPath*) apply->getScope();
    115         }
    116         SkMatrix m;
    117         m.reset();
    118         if (fDraw->addMatrix) {
    119             SkDrawMatrix* matrix;
    120             if (fDraw->addMatrix->getType() == SkType_Matrix)
    121                 matrix = (SkDrawMatrix*) fDraw->addMatrix;
    122             else {
    123                 SkApply* apply = (SkApply*) fDraw->addMatrix;
    124                 apply->refresh(*fMaker);
    125                 apply->activate(*fMaker);
    126                 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
    127                 matrix = (SkDrawMatrix*) apply->getScope();
    128             }
    129             if (matrix) {
    130                 m = matrix->getMatrix();
    131             }
    132         }
    133         SkScalar result = 0;
    134         SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result);
    135         if (drawPath)
    136             dst->addPath(drawPath->getPath(), m);
    137         fMaker->clearExtraPropertyCallBack(fDraw->fType);
    138         return result;
    139     }
    140 
    141 private:
    142     static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) {
    143         if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) {
    144             value->fOperand.fScalar = *(SkScalar*) clen;
    145             value->fType = SkType_Float;
    146             return true;
    147         }
    148         return false;
    149     }
    150 
    151     static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) {
    152         if (SK_LITERAL_STR_EQUAL("distance", token, len)) {
    153             value->fOperand.fScalar = *(SkScalar*) dist;
    154             value->fType = SkType_Float;
    155             return true;
    156         }
    157         return false;
    158     }
    159 
    160     SkDrawShape1DPathEffect* fDraw;
    161     SkAnimateMaker* fMaker;
    162 };
    163 
    164 //////////// SkDrawShapePathEffect
    165 
    166 #if SK_USE_CONDENSED_INFO == 0
    167 
    168 const SkMemberInfo SkDrawShapePathEffect::fInfo[] = {
    169     SK_MEMBER(addMatrix, Drawable), // either matrix or apply
    170     SK_MEMBER(addPath, Drawable),   // either path or apply
    171     SK_MEMBER(path, Path),
    172 };
    173 
    174 #endif
    175 
    176 DEFINE_GET_MEMBER(SkDrawShapePathEffect);
    177 
    178 SkDrawShapePathEffect::SkDrawShapePathEffect() :
    179     addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
    180 }
    181 
    182 SkDrawShapePathEffect::~SkDrawShapePathEffect() {
    183     SkSafeUnref(fPathEffect);
    184 }
    185 
    186 bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
    187     path = (SkDrawPath*) child;
    188     return true;
    189 }
    190 
    191 SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
    192     fPathEffect->ref();
    193     return fPathEffect;
    194 }
    195 
    196 //////////// SkDrawShape1DPathEffect
    197 
    198 #if SK_USE_CONDENSED_INFO == 0
    199 
    200 const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
    201     SK_MEMBER_INHERITED,
    202     SK_MEMBER(phase, String),
    203     SK_MEMBER(spacing, String),
    204 };
    205 
    206 #endif
    207 
    208 DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
    209 
    210 SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
    211 }
    212 
    213 SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
    214 }
    215 
    216 void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) {
    217     if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false))
    218         maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
    219     else
    220         fPathEffect = new SkShape1DPathEffect(this, &maker);
    221 }
    222 
    223 ////////// SkShape2DPathEffect
    224 
    225 class SkShape2DPathEffect : public Sk2DPathEffect {
    226 public:
    227     SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
    228         const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
    229     }
    230 
    231 protected:
    232     virtual void begin(const SkIRect& uvBounds, SkPath*) const SK_OVERRIDE {
    233         const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
    234     }
    235 
    236     virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE {
    237         const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
    238     }
    239 
    240 private:
    241     void setUVBounds(const SkIRect& uvBounds) {
    242         fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
    243             SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
    244     }
    245 
    246     void addPath(const SkPoint& loc, int u, int v, SkPath* dst) {
    247         fLoc = loc;
    248         fU = u;
    249         fV = v;
    250         SkDrawPath* drawPath;
    251         fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
    252         if (fDraw->addPath->isPath()) {
    253             drawPath = (SkDrawPath*) fDraw->addPath;
    254         } else {
    255             SkApply* apply = (SkApply*) fDraw->addPath;
    256             apply->refresh(*fMaker);
    257             apply->activate(*fMaker);
    258             apply->interpolate(*fMaker, v);
    259             drawPath = (SkDrawPath*) apply->getScope();
    260         }
    261         if (drawPath == NULL)
    262             goto clearCallBack;
    263         if (fDraw->matrix) {
    264             SkDrawMatrix* matrix;
    265             if (fDraw->matrix->getType() == SkType_Matrix)
    266                 matrix = (SkDrawMatrix*) fDraw->matrix;
    267             else {
    268                 SkApply* apply = (SkApply*) fDraw->matrix;
    269                 apply->activate(*fMaker);
    270                 apply->interpolate(*fMaker, v);
    271                 matrix = (SkDrawMatrix*) apply->getScope();
    272             }
    273             if (matrix) {
    274                 dst->addPath(drawPath->getPath(), matrix->getMatrix());
    275                 goto clearCallBack;
    276             }
    277         }
    278         dst->addPath(drawPath->getPath());
    279 clearCallBack:
    280         fMaker->clearExtraPropertyCallBack(fDraw->fType);
    281     }
    282 
    283     static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
    284         static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
    285         SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
    286         int index;
    287         if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
    288             return false;
    289         SkASSERT((sizeof(SkPoint) +     sizeof(SkRect)) / sizeof(SkScalar) == 6);
    290         if (index < 6) {
    291             value->fType = SkType_Float;
    292             value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
    293         } else {
    294             value->fType = SkType_Int;
    295             value->fOperand.fS32 = (&shape2D->fU)[index - 6];
    296         }
    297         return true;
    298     }
    299 
    300     SkPoint fLoc;
    301     SkRect fUVBounds;
    302     int32_t fU;
    303     int32_t fV;
    304     SkDrawShape2DPathEffect* fDraw;
    305     SkAnimateMaker* fMaker;
    306 
    307     // illegal
    308     SkShape2DPathEffect(const SkShape2DPathEffect&);
    309     SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
    310 };
    311 
    312 ////////// SkDrawShape2DPathEffect
    313 
    314 #if SK_USE_CONDENSED_INFO == 0
    315 
    316 const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
    317     SK_MEMBER_INHERITED,
    318     SK_MEMBER(matrix, Matrix)
    319 };
    320 
    321 #endif
    322 
    323 DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
    324 
    325 SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
    326 }
    327 
    328 SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
    329 }
    330 
    331 void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
    332     if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
    333             matrix == NULL)
    334         maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
    335     else
    336         fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
    337 }
    338 
    339 ////////// SkDrawComposePathEffect
    340 
    341 #if SK_USE_CONDENSED_INFO == 0
    342 
    343 const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
    344     SK_MEMBER(effect1, PathEffect),
    345     SK_MEMBER(effect2, PathEffect)
    346 };
    347 
    348 #endif
    349 
    350 DEFINE_GET_MEMBER(SkDrawComposePathEffect);
    351 
    352 SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
    353     effect1(NULL), effect2(NULL) {
    354 }
    355 
    356 SkDrawComposePathEffect::~SkDrawComposePathEffect() {
    357     delete effect1;
    358     delete effect2;
    359 }
    360 
    361 bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
    362     if (effect1 == NULL)
    363         effect1 = (SkDrawPathEffect*) child;
    364     else
    365         effect2 = (SkDrawPathEffect*) child;
    366     return true;
    367 }
    368 
    369 SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
    370     SkPathEffect* e1 = effect1->getPathEffect();
    371     SkPathEffect* e2 = effect2->getPathEffect();
    372     SkPathEffect* composite = SkComposePathEffect::Create(e1, e2);
    373     e1->unref();
    374     e2->unref();
    375     return composite;
    376 }
    377 
    378 bool SkDrawComposePathEffect::isPaint() const {
    379     return true;
    380 }
    381 
    382 //////////// SkDrawCornerPathEffect
    383 
    384 #if SK_USE_CONDENSED_INFO == 0
    385 
    386 const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
    387     SK_MEMBER(radius, Float)
    388 };
    389 
    390 #endif
    391 
    392 DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
    393 
    394 SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
    395     fType(type), radius(0) {
    396 }
    397 
    398 SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
    399 }
    400 
    401 SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
    402     return SkCornerPathEffect::Create(radius);
    403 }
    404 
    405 /////////
    406 
    407 #include "SkExtras.h"
    408 
    409 const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
    410 const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
    411 const char kDrawComposePathEffectName[] = "pathEffect:compose";
    412 const char kDrawCornerPathEffectName[]  = "pathEffect:corner";
    413 
    414 class SkExtraPathEffects : public SkExtras {
    415 public:
    416     SkExtraPathEffects() :
    417             skDrawShape1DPathEffectType(SkType_Unknown),
    418             skDrawShape2DPathEffectType(SkType_Unknown),
    419             skDrawComposePathEffectType(SkType_Unknown),
    420             skDrawCornerPathEffectType(SkType_Unknown) {
    421     }
    422 
    423     virtual SkDisplayable* createInstance(SkDisplayTypes type) {
    424         SkDisplayable* result = NULL;
    425         if (skDrawShape1DPathEffectType == type)
    426             result = new SkDrawShape1DPathEffect(type);
    427         else if (skDrawShape2DPathEffectType == type)
    428             result = new SkDrawShape2DPathEffect(type);
    429         else if (skDrawComposePathEffectType == type)
    430             result = new SkDrawComposePathEffect(type);
    431         else if (skDrawCornerPathEffectType == type)
    432             result = new SkDrawCornerPathEffect(type);
    433         return result;
    434     }
    435 
    436     virtual bool definesType(SkDisplayTypes type) {
    437         return type == skDrawShape1DPathEffectType ||
    438             type == skDrawShape2DPathEffectType ||
    439             type == skDrawComposePathEffectType ||
    440             type == skDrawCornerPathEffectType;
    441     }
    442 
    443 #if SK_USE_CONDENSED_INFO == 0
    444     virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
    445         const SkMemberInfo* info = NULL;
    446         int infoCount = 0;
    447         if (skDrawShape1DPathEffectType == type) {
    448             info = SkDrawShape1DPathEffect::fInfo;
    449             infoCount = SkDrawShape1DPathEffect::fInfoCount;
    450         } else if (skDrawShape2DPathEffectType == type) {
    451             info = SkDrawShape2DPathEffect::fInfo;
    452             infoCount = SkDrawShape2DPathEffect::fInfoCount;
    453         } else if (skDrawComposePathEffectType == type) {
    454             info = SkDrawComposePathEffect::fInfo;
    455             infoCount = SkDrawShape1DPathEffect::fInfoCount;
    456         } else if (skDrawCornerPathEffectType == type) {
    457             info = SkDrawCornerPathEffect::fInfo;
    458             infoCount = SkDrawCornerPathEffect::fInfoCount;
    459         }
    460         if (infoCountPtr)
    461             *infoCountPtr = infoCount;
    462         return info;
    463     }
    464 #endif
    465 
    466 #ifdef SK_DEBUG
    467     virtual const char* getName(SkDisplayTypes type) {
    468         if (skDrawShape1DPathEffectType == type)
    469             return kDrawShape1DPathEffectName;
    470         else if (skDrawShape2DPathEffectType == type)
    471             return kDrawShape2DPathEffectName;
    472         else if (skDrawComposePathEffectType == type)
    473             return kDrawComposePathEffectName;
    474         else if (skDrawCornerPathEffectType == type)
    475             return kDrawCornerPathEffectName;
    476         return NULL;
    477     }
    478 #endif
    479 
    480     virtual SkDisplayTypes getType(const char name[], size_t len ) {
    481         SkDisplayTypes* type = NULL;
    482         if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
    483             type = &skDrawShape1DPathEffectType;
    484         else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
    485             type = &skDrawShape2DPathEffectType;
    486         else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
    487             type = &skDrawComposePathEffectType;
    488         else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
    489             type = &skDrawCornerPathEffectType;
    490         if (type) {
    491             if (*type == SkType_Unknown)
    492                 *type = SkDisplayType::RegisterNewType();
    493             return *type;
    494         }
    495         return SkType_Unknown;
    496     }
    497 
    498 private:
    499     SkDisplayTypes skDrawShape1DPathEffectType;
    500     SkDisplayTypes skDrawShape2DPathEffectType;
    501     SkDisplayTypes skDrawComposePathEffectType;
    502     SkDisplayTypes skDrawCornerPathEffectType;
    503 };
    504 
    505 void InitializeSkExtraPathEffects(SkAnimator* animator) {
    506     animator->addExtras(new SkExtraPathEffects());
    507 }
    508 
    509 ////////////////
    510 
    511 
    512 SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
    513 }
    514