blob: 8cfde258048ac683e80162e63b91fac77e6f828f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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();
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000025 virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026 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();
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000063 virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 virtual SkPathEffect* getPathEffect();
reed@google.com82065d62011-02-07 15:30:46 +000065 virtual bool isPaint() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000066private:
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
djsollen@google.comba28d032012-03-26 17:57:35 +000094 SK_DECLARE_UNFLATTENABLE_OBJECT()
95
reed@android.com8a1c16f2008-12-17 15:59:43 +000096protected:
reed@google.com548a1f32012-12-18 16:12:09 +000097 virtual SkScalar begin(SkScalar contourLength) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 SkScriptValue value;
99 SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
100 engine.propertyCallBack(GetContourLength, &contourLength);
101 value.fOperand.fScalar = 0;
102 engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float);
103 return value.fOperand.fScalar;
104 }
105
reed@google.com548a1f32012-12-18 16:12:09 +0000106 virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 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;
reed@google.com82065d62011-02-07 15:30:46 +0000122 if (fDraw->addMatrix->getType() == SkType_Matrix)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123 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
140private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141 static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) {
142 if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) {
143 value->fOperand.fScalar = *(SkScalar*) clen;
144 value->fType = SkType_Float;
145 return true;
146 }
147 return false;
148 }
149
150 static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) {
151 if (SK_LITERAL_STR_EQUAL("distance", token, len)) {
152 value->fOperand.fScalar = *(SkScalar*) dist;
153 value->fType = SkType_Float;
154 return true;
155 }
156 return false;
157 }
158
159 SkDrawShape1DPathEffect* fDraw;
160 SkAnimateMaker* fMaker;
161};
162
163//////////// SkDrawShapePathEffect
164
165#if SK_USE_CONDENSED_INFO == 0
166
167const SkMemberInfo SkDrawShapePathEffect::fInfo[] = {
168 SK_MEMBER(addMatrix, Drawable), // either matrix or apply
169 SK_MEMBER(addPath, Drawable), // either path or apply
170 SK_MEMBER(path, Path),
171};
172
173#endif
174
175DEFINE_GET_MEMBER(SkDrawShapePathEffect);
176
reed@google.com82065d62011-02-07 15:30:46 +0000177SkDrawShapePathEffect::SkDrawShapePathEffect() :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
179}
180
181SkDrawShapePathEffect::~SkDrawShapePathEffect() {
reed@google.com82065d62011-02-07 15:30:46 +0000182 SkSafeUnref(fPathEffect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183}
184
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000185bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 path = (SkDrawPath*) child;
187 return true;
188}
189
190SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
191 fPathEffect->ref();
192 return fPathEffect;
193}
194
195//////////// SkDrawShape1DPathEffect
196
197#if SK_USE_CONDENSED_INFO == 0
198
199const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
200 SK_MEMBER_INHERITED,
201 SK_MEMBER(phase, String),
202 SK_MEMBER(spacing, String),
203};
204
205#endif
206
207DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
208
209SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
210}
211
212SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
213}
214
215void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) {
216 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false))
217 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
218 else
219 fPathEffect = new SkShape1DPathEffect(this, &maker);
220}
221
222////////// SkShape2DPathEffect
223
224class SkShape2DPathEffect : public Sk2DPathEffect {
225public:
reed@google.com82065d62011-02-07 15:30:46 +0000226 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
228 }
229
230protected:
231 virtual void begin(const SkIRect& uvBounds, SkPath* )
232 {
233 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
234 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
235 }
236
237 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst)
238 {
239 fLoc = loc;
240 fU = u;
241 fV = v;
242 SkDrawPath* drawPath;
243 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
244 if (fDraw->addPath->isPath()) {
245 drawPath = (SkDrawPath*) fDraw->addPath;
246 } else {
247 SkApply* apply = (SkApply*) fDraw->addPath;
248 apply->refresh(*fMaker);
249 apply->activate(*fMaker);
250 apply->interpolate(*fMaker, v);
251 drawPath = (SkDrawPath*) apply->getScope();
252 }
253 if (drawPath == NULL)
254 goto clearCallBack;
255 if (fDraw->matrix) {
256 SkDrawMatrix* matrix;
reed@google.com82065d62011-02-07 15:30:46 +0000257 if (fDraw->matrix->getType() == SkType_Matrix)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258 matrix = (SkDrawMatrix*) fDraw->matrix;
259 else {
260 SkApply* apply = (SkApply*) fDraw->matrix;
261 apply->activate(*fMaker);
262 apply->interpolate(*fMaker, v);
263 matrix = (SkDrawMatrix*) apply->getScope();
264 }
265 if (matrix) {
266 dst->addPath(drawPath->getPath(), matrix->getMatrix());
267 goto clearCallBack;
268 }
269 }
270 dst->addPath(drawPath->getPath());
271clearCallBack:
272 fMaker->clearExtraPropertyCallBack(fDraw->fType);
273 }
274
275private:
276
277 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
278 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
279 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
280 int index;
281 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
282 return false;
283 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6);
284 if (index < 6) {
285 value->fType = SkType_Float;
286 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
287 } else {
288 value->fType = SkType_Int;
289 value->fOperand.fS32 = (&shape2D->fU)[index - 6];
290 }
291 return true;
292 }
reed@google.com82065d62011-02-07 15:30:46 +0000293
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294 SkPoint fLoc;
295 SkRect fUVBounds;
296 int32_t fU;
297 int32_t fV;
298 SkDrawShape2DPathEffect* fDraw;
299 SkAnimateMaker* fMaker;
300
301 // illegal
302 SkShape2DPathEffect(const SkShape2DPathEffect&);
303 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
304};
305
306////////// SkDrawShape2DPathEffect
307
308#if SK_USE_CONDENSED_INFO == 0
309
310const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
311 SK_MEMBER_INHERITED,
312 SK_MEMBER(matrix, Matrix)
313};
314
315#endif
316
317DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
318
319SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
320}
321
322SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
323}
324
325void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
326 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
327 matrix == NULL)
328 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
329 else
330 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
331}
332
333////////// SkDrawComposePathEffect
334
335#if SK_USE_CONDENSED_INFO == 0
336
337const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
338 SK_MEMBER(effect1, PathEffect),
339 SK_MEMBER(effect2, PathEffect)
340};
341
342#endif
343
344DEFINE_GET_MEMBER(SkDrawComposePathEffect);
345
346SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
347 effect1(NULL), effect2(NULL) {
348}
349
350SkDrawComposePathEffect::~SkDrawComposePathEffect() {
351 delete effect1;
352 delete effect2;
353}
354
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000355bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000356 if (effect1 == NULL)
357 effect1 = (SkDrawPathEffect*) child;
358 else
359 effect2 = (SkDrawPathEffect*) child;
360 return true;
361}
362
363SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
364 SkPathEffect* e1 = effect1->getPathEffect();
365 SkPathEffect* e2 = effect2->getPathEffect();
366 SkPathEffect* composite = new SkComposePathEffect(e1, e2);
367 e1->unref();
368 e2->unref();
369 return composite;
370}
371
372bool SkDrawComposePathEffect::isPaint() const {
373 return true;
374}
375
376//////////// SkDrawCornerPathEffect
377
378#if SK_USE_CONDENSED_INFO == 0
379
380const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
381 SK_MEMBER(radius, Float)
382};
383
384#endif
385
386DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
387
388SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
389 fType(type), radius(0) {
390}
391
392SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
393}
394
395SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
396 return new SkCornerPathEffect(radius);
397}
398
399/////////
400
401#include "SkExtras.h"
402
403const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
404const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
405const char kDrawComposePathEffectName[] = "pathEffect:compose";
406const char kDrawCornerPathEffectName[] = "pathEffect:corner";
407
408class SkExtraPathEffects : public SkExtras {
409public:
reed@google.com82065d62011-02-07 15:30:46 +0000410 SkExtraPathEffects(SkAnimator* animator) :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000411 skDrawShape1DPathEffectType(SkType_Unknown),
412 skDrawShape2DPathEffectType(SkType_Unknown),
413 skDrawComposePathEffectType(SkType_Unknown),
414 skDrawCornerPathEffectType(SkType_Unknown) {
415 }
reed@google.com82065d62011-02-07 15:30:46 +0000416
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417 virtual SkDisplayable* createInstance(SkDisplayTypes type) {
418 SkDisplayable* result = NULL;
419 if (skDrawShape1DPathEffectType == type)
420 result = new SkDrawShape1DPathEffect(type);
421 else if (skDrawShape2DPathEffectType == type)
422 result = new SkDrawShape2DPathEffect(type);
423 else if (skDrawComposePathEffectType == type)
424 result = new SkDrawComposePathEffect(type);
425 else if (skDrawCornerPathEffectType == type)
426 result = new SkDrawCornerPathEffect(type);
427 return result;
428 }
429
430 virtual bool definesType(SkDisplayTypes type) {
reed@google.com82065d62011-02-07 15:30:46 +0000431 return type == skDrawShape1DPathEffectType ||
432 type == skDrawShape2DPathEffectType ||
reed@android.com8a1c16f2008-12-17 15:59:43 +0000433 type == skDrawComposePathEffectType ||
434 type == skDrawCornerPathEffectType;
435 }
436
437#if SK_USE_CONDENSED_INFO == 0
438 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
439 const SkMemberInfo* info = NULL;
440 int infoCount = 0;
441 if (skDrawShape1DPathEffectType == type) {
442 info = SkDrawShape1DPathEffect::fInfo;
443 infoCount = SkDrawShape1DPathEffect::fInfoCount;
444 } else if (skDrawShape2DPathEffectType == type) {
445 info = SkDrawShape2DPathEffect::fInfo;
446 infoCount = SkDrawShape2DPathEffect::fInfoCount;
447 } else if (skDrawComposePathEffectType == type) {
448 info = SkDrawComposePathEffect::fInfo;
449 infoCount = SkDrawShape1DPathEffect::fInfoCount;
450 } else if (skDrawCornerPathEffectType == type) {
451 info = SkDrawCornerPathEffect::fInfo;
452 infoCount = SkDrawCornerPathEffect::fInfoCount;
453 }
454 if (infoCountPtr)
455 *infoCountPtr = infoCount;
456 return info;
457 }
458#endif
459
460#ifdef SK_DEBUG
461 virtual const char* getName(SkDisplayTypes type) {
462 if (skDrawShape1DPathEffectType == type)
463 return kDrawShape1DPathEffectName;
464 else if (skDrawShape2DPathEffectType == type)
465 return kDrawShape2DPathEffectName;
466 else if (skDrawComposePathEffectType == type)
467 return kDrawComposePathEffectName;
468 else if (skDrawCornerPathEffectType == type)
469 return kDrawCornerPathEffectName;
470 return NULL;
471 }
472#endif
473
474 virtual SkDisplayTypes getType(const char name[], size_t len ) {
475 SkDisplayTypes* type = NULL;
476 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
477 type = &skDrawShape1DPathEffectType;
478 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
479 type = &skDrawShape2DPathEffectType;
480 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
481 type = &skDrawComposePathEffectType;
482 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
483 type = &skDrawCornerPathEffectType;
484 if (type) {
485 if (*type == SkType_Unknown)
486 *type = SkDisplayType::RegisterNewType();
487 return *type;
488 }
489 return SkType_Unknown;
490 }
491
492private:
493 SkDisplayTypes skDrawShape1DPathEffectType;
494 SkDisplayTypes skDrawShape2DPathEffectType;
495 SkDisplayTypes skDrawComposePathEffectType;
496 SkDisplayTypes skDrawCornerPathEffectType;
497};
498
499
500void InitializeSkExtraPathEffects(SkAnimator* animator) {
501 animator->addExtras(new SkExtraPathEffects(animator));
502}
503
504////////////////
505
506
507SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
508}