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