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