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 add(SkAnimateMaker& , SkDisplayable* );
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 add(SkAnimateMaker& , SkDisplayable* );
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
94protected:
95    virtual SkScalar begin(SkScalar contourLength)
96    {
97        SkScriptValue value;
98        SkAnimatorScript engine(*fMaker, NULL, 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    virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure& )
106    {
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, SkScalarMulRound(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, SkScalarMulRound(distance, 1000));
129                matrix = (SkDrawMatrix*) apply->getScope();
130            }
131        }
132        SkScalar result = 0;
133        SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result);
134        if (drawPath)
135            dst->addPath(drawPath->getPath(), m);
136        fMaker->clearExtraPropertyCallBack(fDraw->fType);
137        return result;
138    }
139
140private:
141    virtual void flatten(SkFlattenableWriteBuffer& ) {}
142    virtual Factory getFactory() { return NULL; }
143
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::add(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* )
235    {
236        fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
237            SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
238    }
239
240    virtual void next(const SkPoint& loc, int u, int v, SkPath* dst)
241    {
242        fLoc = loc;
243        fU = u;
244        fV = v;
245        SkDrawPath* drawPath;
246        fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
247        if (fDraw->addPath->isPath()) {
248            drawPath = (SkDrawPath*) fDraw->addPath;
249        } else {
250            SkApply* apply = (SkApply*) fDraw->addPath;
251            apply->refresh(*fMaker);
252            apply->activate(*fMaker);
253            apply->interpolate(*fMaker, v);
254            drawPath = (SkDrawPath*) apply->getScope();
255        }
256        if (drawPath == NULL)
257            goto clearCallBack;
258        if (fDraw->matrix) {
259            SkDrawMatrix* matrix;
260            if (fDraw->matrix->getType() == SkType_Matrix)
261                matrix = (SkDrawMatrix*) fDraw->matrix;
262            else {
263                SkApply* apply = (SkApply*) fDraw->matrix;
264                apply->activate(*fMaker);
265                apply->interpolate(*fMaker, v);
266                matrix = (SkDrawMatrix*) apply->getScope();
267            }
268            if (matrix) {
269                dst->addPath(drawPath->getPath(), matrix->getMatrix());
270                goto clearCallBack;
271            }
272        }
273        dst->addPath(drawPath->getPath());
274clearCallBack:
275        fMaker->clearExtraPropertyCallBack(fDraw->fType);
276    }
277
278private:
279
280    static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
281        static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
282        SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
283        int index;
284        if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
285            return false;
286        SkASSERT((sizeof(SkPoint) +     sizeof(SkRect)) / sizeof(SkScalar) == 6);
287        if (index < 6) {
288            value->fType = SkType_Float;
289            value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
290        } else {
291            value->fType = SkType_Int;
292            value->fOperand.fS32 = (&shape2D->fU)[index - 6];
293        }
294        return true;
295    }
296
297    SkPoint fLoc;
298    SkRect fUVBounds;
299    int32_t fU;
300    int32_t fV;
301    SkDrawShape2DPathEffect* fDraw;
302    SkAnimateMaker* fMaker;
303
304    // illegal
305    SkShape2DPathEffect(const SkShape2DPathEffect&);
306    SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
307};
308
309////////// SkDrawShape2DPathEffect
310
311#if SK_USE_CONDENSED_INFO == 0
312
313const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
314    SK_MEMBER_INHERITED,
315    SK_MEMBER(matrix, Matrix)
316};
317
318#endif
319
320DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
321
322SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
323}
324
325SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
326}
327
328void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
329    if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
330            matrix == NULL)
331        maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
332    else
333        fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
334}
335
336////////// SkDrawComposePathEffect
337
338#if SK_USE_CONDENSED_INFO == 0
339
340const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
341    SK_MEMBER(effect1, PathEffect),
342    SK_MEMBER(effect2, PathEffect)
343};
344
345#endif
346
347DEFINE_GET_MEMBER(SkDrawComposePathEffect);
348
349SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
350    effect1(NULL), effect2(NULL) {
351}
352
353SkDrawComposePathEffect::~SkDrawComposePathEffect() {
354    delete effect1;
355    delete effect2;
356}
357
358bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) {
359    if (effect1 == NULL)
360        effect1 = (SkDrawPathEffect*) child;
361    else
362        effect2 = (SkDrawPathEffect*) child;
363    return true;
364}
365
366SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
367    SkPathEffect* e1 = effect1->getPathEffect();
368    SkPathEffect* e2 = effect2->getPathEffect();
369    SkPathEffect* composite = new SkComposePathEffect(e1, e2);
370    e1->unref();
371    e2->unref();
372    return composite;
373}
374
375bool SkDrawComposePathEffect::isPaint() const {
376    return true;
377}
378
379//////////// SkDrawCornerPathEffect
380
381#if SK_USE_CONDENSED_INFO == 0
382
383const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
384    SK_MEMBER(radius, Float)
385};
386
387#endif
388
389DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
390
391SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
392    fType(type), radius(0) {
393}
394
395SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
396}
397
398SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
399    return new SkCornerPathEffect(radius);
400}
401
402/////////
403
404#include "SkExtras.h"
405
406const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
407const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
408const char kDrawComposePathEffectName[] = "pathEffect:compose";
409const char kDrawCornerPathEffectName[]  = "pathEffect:corner";
410
411class SkExtraPathEffects : public SkExtras {
412public:
413    SkExtraPathEffects(SkAnimator* animator) :
414            skDrawShape1DPathEffectType(SkType_Unknown),
415            skDrawShape2DPathEffectType(SkType_Unknown),
416            skDrawComposePathEffectType(SkType_Unknown),
417            skDrawCornerPathEffectType(SkType_Unknown) {
418    }
419
420    virtual SkDisplayable* createInstance(SkDisplayTypes type) {
421        SkDisplayable* result = NULL;
422        if (skDrawShape1DPathEffectType == type)
423            result = new SkDrawShape1DPathEffect(type);
424        else if (skDrawShape2DPathEffectType == type)
425            result = new SkDrawShape2DPathEffect(type);
426        else if (skDrawComposePathEffectType == type)
427            result = new SkDrawComposePathEffect(type);
428        else if (skDrawCornerPathEffectType == type)
429            result = new SkDrawCornerPathEffect(type);
430        return result;
431    }
432
433    virtual bool definesType(SkDisplayTypes type) {
434        return type == skDrawShape1DPathEffectType ||
435            type == skDrawShape2DPathEffectType ||
436            type == skDrawComposePathEffectType ||
437            type == skDrawCornerPathEffectType;
438    }
439
440#if SK_USE_CONDENSED_INFO == 0
441    virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
442        const SkMemberInfo* info = NULL;
443        int infoCount = 0;
444        if (skDrawShape1DPathEffectType == type) {
445            info = SkDrawShape1DPathEffect::fInfo;
446            infoCount = SkDrawShape1DPathEffect::fInfoCount;
447        } else if (skDrawShape2DPathEffectType == type) {
448            info = SkDrawShape2DPathEffect::fInfo;
449            infoCount = SkDrawShape2DPathEffect::fInfoCount;
450        } else if (skDrawComposePathEffectType == type) {
451            info = SkDrawComposePathEffect::fInfo;
452            infoCount = SkDrawShape1DPathEffect::fInfoCount;
453        } else if (skDrawCornerPathEffectType == type) {
454            info = SkDrawCornerPathEffect::fInfo;
455            infoCount = SkDrawCornerPathEffect::fInfoCount;
456        }
457        if (infoCountPtr)
458            *infoCountPtr = infoCount;
459        return info;
460    }
461#endif
462
463#ifdef SK_DEBUG
464    virtual const char* getName(SkDisplayTypes type) {
465        if (skDrawShape1DPathEffectType == type)
466            return kDrawShape1DPathEffectName;
467        else if (skDrawShape2DPathEffectType == type)
468            return kDrawShape2DPathEffectName;
469        else if (skDrawComposePathEffectType == type)
470            return kDrawComposePathEffectName;
471        else if (skDrawCornerPathEffectType == type)
472            return kDrawCornerPathEffectName;
473        return NULL;
474    }
475#endif
476
477    virtual SkDisplayTypes getType(const char name[], size_t len ) {
478        SkDisplayTypes* type = NULL;
479        if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
480            type = &skDrawShape1DPathEffectType;
481        else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
482            type = &skDrawShape2DPathEffectType;
483        else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
484            type = &skDrawComposePathEffectType;
485        else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
486            type = &skDrawCornerPathEffectType;
487        if (type) {
488            if (*type == SkType_Unknown)
489                *type = SkDisplayType::RegisterNewType();
490            return *type;
491        }
492        return SkType_Unknown;
493    }
494
495private:
496    SkDisplayTypes skDrawShape1DPathEffectType;
497    SkDisplayTypes skDrawShape2DPathEffectType;
498    SkDisplayTypes skDrawComposePathEffectType;
499    SkDisplayTypes skDrawCornerPathEffectType;
500};
501
502
503void InitializeSkExtraPathEffects(SkAnimator* animator) {
504    animator->addExtras(new SkExtraPathEffects(animator));
505}
506
507////////////////
508
509
510SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
511}
512