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