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