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