• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 class SkDrawShapePathEffect : public SkDrawPathEffect {
22     DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
23     SkDrawShapePathEffect();
24     virtual ~SkDrawShapePathEffect();
25     virtual bool add(SkAnimateMaker& , SkDisplayable* );
26     virtual SkPathEffect* getPathEffect();
27 protected:
28     SkDrawable* addPath;
29     SkDrawable* addMatrix;
30     SkDrawPath* path;
31     SkPathEffect* fPathEffect;
32     friend class SkShape1DPathEffect;
33     friend class SkShape2DPathEffect;
34 };
35 
36 class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
37     DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
38     SkDrawShape1DPathEffect(SkDisplayTypes );
39     virtual ~SkDrawShape1DPathEffect();
40     virtual void onEndElement(SkAnimateMaker& );
41 private:
42     SkString phase;
43     SkString spacing;
44     friend class SkShape1DPathEffect;
45     typedef SkDrawShapePathEffect INHERITED;
46 };
47 
48 class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
49     DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
50     SkDrawShape2DPathEffect(SkDisplayTypes );
51     virtual ~SkDrawShape2DPathEffect();
52     virtual void onEndElement(SkAnimateMaker& );
53 private:
54     SkDrawMatrix* matrix;
55     friend class SkShape2DPathEffect;
56     typedef SkDrawShapePathEffect INHERITED;
57 };
58 
59 class 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;
66 private:
67     SkDrawPathEffect* effect1;
68     SkDrawPathEffect* effect2;
69 };
70 
71 class SkDrawCornerPathEffect : public SkDrawPathEffect {
72     DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
73     SkDrawCornerPathEffect(SkDisplayTypes );
74     virtual ~SkDrawCornerPathEffect();
75     virtual SkPathEffect* getPathEffect();
76 private:
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 
88 class SkShape1DPathEffect : public Sk1DPathEffect {
89 public:
SkShape1DPathEffect(SkDrawShape1DPathEffect * draw,SkAnimateMaker * maker)90     SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
91         fDraw(draw), fMaker(maker) {
92     }
93 
94 protected:
begin(SkScalar contourLength)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 
next(SkPath * dst,SkScalar distance,SkPathMeasure &)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 
140 private:
flatten(SkFlattenableWriteBuffer &)141     virtual void flatten(SkFlattenableWriteBuffer& ) {}
getFactory()142     virtual Factory getFactory() { return NULL; }
143 
GetContourLength(const char * token,size_t len,void * clen,SkScriptValue * value)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 
GetDistance(const char * token,size_t len,void * dist,SkScriptValue * value)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 
170 const 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 
178 DEFINE_GET_MEMBER(SkDrawShapePathEffect);
179 
SkDrawShapePathEffect()180 SkDrawShapePathEffect::SkDrawShapePathEffect() :
181     addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
182 }
183 
~SkDrawShapePathEffect()184 SkDrawShapePathEffect::~SkDrawShapePathEffect() {
185     SkSafeUnref(fPathEffect);
186 }
187 
add(SkAnimateMaker &,SkDisplayable * child)188 bool SkDrawShapePathEffect::add(SkAnimateMaker& , SkDisplayable* child) {
189     path = (SkDrawPath*) child;
190     return true;
191 }
192 
getPathEffect()193 SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
194     fPathEffect->ref();
195     return fPathEffect;
196 }
197 
198 //////////// SkDrawShape1DPathEffect
199 
200 #if SK_USE_CONDENSED_INFO == 0
201 
202 const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
203     SK_MEMBER_INHERITED,
204     SK_MEMBER(phase, String),
205     SK_MEMBER(spacing, String),
206 };
207 
208 #endif
209 
210 DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
211 
SkDrawShape1DPathEffect(SkDisplayTypes type)212 SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
213 }
214 
~SkDrawShape1DPathEffect()215 SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
216 }
217 
onEndElement(SkAnimateMaker & maker)218 void 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 
227 class SkShape2DPathEffect : public Sk2DPathEffect {
228 public:
SkShape2DPathEffect(SkDrawShape2DPathEffect * draw,SkAnimateMaker * maker,const SkMatrix & matrix)229     SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
230         const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
231     }
232 
233 protected:
begin(const SkIRect & uvBounds,SkPath *)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 
next(const SkPoint & loc,int u,int v,SkPath * dst)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());
274 clearCallBack:
275         fMaker->clearExtraPropertyCallBack(fDraw->fType);
276     }
277 
278 private:
279 
Get2D(const char * token,size_t len,void * s2D,SkScriptValue * value)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 
313 const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
314     SK_MEMBER_INHERITED,
315     SK_MEMBER(matrix, Matrix)
316 };
317 
318 #endif
319 
320 DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
321 
SkDrawShape2DPathEffect(SkDisplayTypes type)322 SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
323 }
324 
~SkDrawShape2DPathEffect()325 SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
326 }
327 
onEndElement(SkAnimateMaker & maker)328 void 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 
340 const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
341     SK_MEMBER(effect1, PathEffect),
342     SK_MEMBER(effect2, PathEffect)
343 };
344 
345 #endif
346 
347 DEFINE_GET_MEMBER(SkDrawComposePathEffect);
348 
SkDrawComposePathEffect(SkDisplayTypes type)349 SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
350     effect1(NULL), effect2(NULL) {
351 }
352 
~SkDrawComposePathEffect()353 SkDrawComposePathEffect::~SkDrawComposePathEffect() {
354     delete effect1;
355     delete effect2;
356 }
357 
add(SkAnimateMaker &,SkDisplayable * child)358 bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) {
359     if (effect1 == NULL)
360         effect1 = (SkDrawPathEffect*) child;
361     else
362         effect2 = (SkDrawPathEffect*) child;
363     return true;
364 }
365 
getPathEffect()366 SkPathEffect* 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 
isPaint() const375 bool SkDrawComposePathEffect::isPaint() const {
376     return true;
377 }
378 
379 //////////// SkDrawCornerPathEffect
380 
381 #if SK_USE_CONDENSED_INFO == 0
382 
383 const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
384     SK_MEMBER(radius, Float)
385 };
386 
387 #endif
388 
389 DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
390 
SkDrawCornerPathEffect(SkDisplayTypes type)391 SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
392     fType(type), radius(0) {
393 }
394 
~SkDrawCornerPathEffect()395 SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
396 }
397 
getPathEffect()398 SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
399     return new SkCornerPathEffect(radius);
400 }
401 
402 /////////
403 
404 #include "SkExtras.h"
405 
406 const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
407 const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
408 const char kDrawComposePathEffectName[] = "pathEffect:compose";
409 const char kDrawCornerPathEffectName[]  = "pathEffect:corner";
410 
411 class SkExtraPathEffects : public SkExtras {
412 public:
SkExtraPathEffects(SkAnimator * animator)413     SkExtraPathEffects(SkAnimator* animator) :
414             skDrawShape1DPathEffectType(SkType_Unknown),
415             skDrawShape2DPathEffectType(SkType_Unknown),
416             skDrawComposePathEffectType(SkType_Unknown),
417             skDrawCornerPathEffectType(SkType_Unknown) {
418     }
419 
createInstance(SkDisplayTypes type)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 
definesType(SkDisplayTypes type)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
getMembers(SkDisplayTypes type,int * infoCountPtr)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
getName(SkDisplayTypes type)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 
getType(const char name[],size_t len)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 
495 private:
496     SkDisplayTypes skDrawShape1DPathEffectType;
497     SkDisplayTypes skDrawShape2DPathEffectType;
498     SkDisplayTypes skDrawComposePathEffectType;
499     SkDisplayTypes skDrawCornerPathEffectType;
500 };
501 
502 
InitializeSkExtraPathEffects(SkAnimator * animator)503 void InitializeSkExtraPathEffects(SkAnimator* animator) {
504     animator->addExtras(new SkExtraPathEffects(animator));
505 }
506 
507 ////////////////
508 
509 
SkExtras()510 SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
511 }
512