SkDrawExtraPathEffect.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
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
29class SkDrawShapePathEffect : public SkDrawPathEffect {
30    DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
31    SkDrawShapePathEffect();
32    virtual ~SkDrawShapePathEffect();
33    virtual bool add(SkAnimateMaker& , SkDisplayable* );
34    virtual SkPathEffect* getPathEffect();
35protected:
36    SkDrawable* addPath;
37    SkDrawable* addMatrix;
38    SkDrawPath* path;
39    SkPathEffect* fPathEffect;
40    friend class SkShape1DPathEffect;
41    friend class SkShape2DPathEffect;
42};
43
44class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
45    DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
46    SkDrawShape1DPathEffect(SkDisplayTypes );
47    virtual ~SkDrawShape1DPathEffect();
48    virtual void onEndElement(SkAnimateMaker& );
49private:
50    SkString phase;
51    SkString spacing;
52    friend class SkShape1DPathEffect;
53    typedef SkDrawShapePathEffect INHERITED;
54};
55
56class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
57    DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
58    SkDrawShape2DPathEffect(SkDisplayTypes );
59    virtual ~SkDrawShape2DPathEffect();
60    virtual void onEndElement(SkAnimateMaker& );
61private:
62    SkDrawMatrix* matrix;
63    friend class SkShape2DPathEffect;
64    typedef SkDrawShapePathEffect INHERITED;
65};
66
67class 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;
74private:
75    SkDrawPathEffect* effect1;
76    SkDrawPathEffect* effect2;
77};
78
79class SkDrawCornerPathEffect : public SkDrawPathEffect {
80    DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
81    SkDrawCornerPathEffect(SkDisplayTypes );
82    virtual ~SkDrawCornerPathEffect();
83    virtual SkPathEffect* getPathEffect();
84private:
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
96class SkShape1DPathEffect : public Sk1DPathEffect {
97public:
98    SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
99        fDraw(draw), fMaker(maker) {
100    }
101
102protected:
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
148private:
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
178const 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
186DEFINE_GET_MEMBER(SkDrawShapePathEffect);
187
188SkDrawShapePathEffect::SkDrawShapePathEffect() :
189    addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
190}
191
192SkDrawShapePathEffect::~SkDrawShapePathEffect() {
193    fPathEffect->safeUnref();
194}
195
196bool SkDrawShapePathEffect::add(SkAnimateMaker& , SkDisplayable* child) {
197    path = (SkDrawPath*) child;
198    return true;
199}
200
201SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
202    fPathEffect->ref();
203    return fPathEffect;
204}
205
206//////////// SkDrawShape1DPathEffect
207
208#if SK_USE_CONDENSED_INFO == 0
209
210const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
211    SK_MEMBER_INHERITED,
212    SK_MEMBER(phase, String),
213    SK_MEMBER(spacing, String),
214};
215
216#endif
217
218DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
219
220SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
221}
222
223SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
224}
225
226void 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
235class SkShape2DPathEffect : public Sk2DPathEffect {
236public:
237    SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
238        const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
239    }
240
241protected:
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());
282clearCallBack:
283        fMaker->clearExtraPropertyCallBack(fDraw->fType);
284    }
285
286private:
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
321const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
322    SK_MEMBER_INHERITED,
323    SK_MEMBER(matrix, Matrix)
324};
325
326#endif
327
328DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
329
330SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
331}
332
333SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
334}
335
336void 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
348const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
349    SK_MEMBER(effect1, PathEffect),
350    SK_MEMBER(effect2, PathEffect)
351};
352
353#endif
354
355DEFINE_GET_MEMBER(SkDrawComposePathEffect);
356
357SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
358    effect1(NULL), effect2(NULL) {
359}
360
361SkDrawComposePathEffect::~SkDrawComposePathEffect() {
362    delete effect1;
363    delete effect2;
364}
365
366bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) {
367    if (effect1 == NULL)
368        effect1 = (SkDrawPathEffect*) child;
369    else
370        effect2 = (SkDrawPathEffect*) child;
371    return true;
372}
373
374SkPathEffect* 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
383bool SkDrawComposePathEffect::isPaint() const {
384    return true;
385}
386
387//////////// SkDrawCornerPathEffect
388
389#if SK_USE_CONDENSED_INFO == 0
390
391const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
392    SK_MEMBER(radius, Float)
393};
394
395#endif
396
397DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
398
399SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
400    fType(type), radius(0) {
401}
402
403SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
404}
405
406SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
407    return new SkCornerPathEffect(radius);
408}
409
410/////////
411
412#include "SkExtras.h"
413
414const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
415const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
416const char kDrawComposePathEffectName[] = "pathEffect:compose";
417const char kDrawCornerPathEffectName[]  = "pathEffect:corner";
418
419class SkExtraPathEffects : public SkExtras {
420public:
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
503private:
504    SkDisplayTypes skDrawShape1DPathEffectType;
505    SkDisplayTypes skDrawShape2DPathEffectType;
506    SkDisplayTypes skDrawComposePathEffectType;
507    SkDisplayTypes skDrawCornerPathEffectType;
508};
509
510
511void InitializeSkExtraPathEffects(SkAnimator* animator) {
512    animator->addExtras(new SkExtraPathEffects(animator));
513}
514
515////////////////
516
517
518SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
519}
520