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