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