blob: e973dbf7955cc1b958925a4a8b28573c812c9ce9 [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 }
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000131 if (matrix) {
132 m = matrix->getMatrix();
133 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 }
135 SkScalar result = 0;
136 SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result);
137 if (drawPath)
138 dst->addPath(drawPath->getPath(), m);
139 fMaker->clearExtraPropertyCallBack(fDraw->fType);
140 return result;
141 }
142
143private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 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
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
170const 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
178DEFINE_GET_MEMBER(SkDrawShapePathEffect);
179
reed@google.com82065d62011-02-07 15:30:46 +0000180SkDrawShapePathEffect::SkDrawShapePathEffect() :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
182}
183
184SkDrawShapePathEffect::~SkDrawShapePathEffect() {
reed@google.com82065d62011-02-07 15:30:46 +0000185 SkSafeUnref(fPathEffect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186}
187
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000188bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 path = (SkDrawPath*) child;
190 return true;
191}
192
193SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
194 fPathEffect->ref();
195 return fPathEffect;
196}
197
198//////////// SkDrawShape1DPathEffect
199
200#if SK_USE_CONDENSED_INFO == 0
201
202const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
203 SK_MEMBER_INHERITED,
204 SK_MEMBER(phase, String),
205 SK_MEMBER(spacing, String),
206};
207
208#endif
209
210DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
211
212SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
213}
214
215SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
216}
217
218void 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
227class SkShape2DPathEffect : public Sk2DPathEffect {
228public:
reed@google.com82065d62011-02-07 15:30:46 +0000229 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000230 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
231 }
232
233protected:
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000234 virtual void begin(const SkIRect& uvBounds, SkPath*) const SK_OVERRIDE {
235 const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
236 }
237
238 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE {
239 const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
240 }
241
242private:
243 void setUVBounds(const SkIRect& uvBounds) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
245 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
246 }
247
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000248 void addPath(const SkPoint& loc, int u, int v, SkPath* dst) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000249 fLoc = loc;
250 fU = u;
251 fV = v;
252 SkDrawPath* drawPath;
253 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
254 if (fDraw->addPath->isPath()) {
255 drawPath = (SkDrawPath*) fDraw->addPath;
256 } else {
257 SkApply* apply = (SkApply*) fDraw->addPath;
258 apply->refresh(*fMaker);
259 apply->activate(*fMaker);
260 apply->interpolate(*fMaker, v);
261 drawPath = (SkDrawPath*) apply->getScope();
262 }
263 if (drawPath == NULL)
264 goto clearCallBack;
265 if (fDraw->matrix) {
266 SkDrawMatrix* matrix;
reed@google.com82065d62011-02-07 15:30:46 +0000267 if (fDraw->matrix->getType() == SkType_Matrix)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268 matrix = (SkDrawMatrix*) fDraw->matrix;
269 else {
270 SkApply* apply = (SkApply*) fDraw->matrix;
271 apply->activate(*fMaker);
272 apply->interpolate(*fMaker, v);
273 matrix = (SkDrawMatrix*) apply->getScope();
274 }
275 if (matrix) {
276 dst->addPath(drawPath->getPath(), matrix->getMatrix());
277 goto clearCallBack;
278 }
279 }
280 dst->addPath(drawPath->getPath());
281clearCallBack:
282 fMaker->clearExtraPropertyCallBack(fDraw->fType);
283 }
284
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
286 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
287 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
288 int index;
289 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
290 return false;
291 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6);
292 if (index < 6) {
293 value->fType = SkType_Float;
294 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
295 } else {
296 value->fType = SkType_Int;
297 value->fOperand.fS32 = (&shape2D->fU)[index - 6];
298 }
299 return true;
300 }
reed@google.com82065d62011-02-07 15:30:46 +0000301
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 SkPoint fLoc;
303 SkRect fUVBounds;
304 int32_t fU;
305 int32_t fV;
306 SkDrawShape2DPathEffect* fDraw;
307 SkAnimateMaker* fMaker;
308
309 // illegal
310 SkShape2DPathEffect(const SkShape2DPathEffect&);
311 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
312};
313
314////////// SkDrawShape2DPathEffect
315
316#if SK_USE_CONDENSED_INFO == 0
317
318const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
319 SK_MEMBER_INHERITED,
320 SK_MEMBER(matrix, Matrix)
321};
322
323#endif
324
325DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
326
327SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
328}
329
330SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
331}
332
333void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
334 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
335 matrix == NULL)
336 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
337 else
338 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
339}
340
341////////// SkDrawComposePathEffect
342
343#if SK_USE_CONDENSED_INFO == 0
344
345const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
346 SK_MEMBER(effect1, PathEffect),
347 SK_MEMBER(effect2, PathEffect)
348};
349
350#endif
351
352DEFINE_GET_MEMBER(SkDrawComposePathEffect);
353
354SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
355 effect1(NULL), effect2(NULL) {
356}
357
358SkDrawComposePathEffect::~SkDrawComposePathEffect() {
359 delete effect1;
360 delete effect2;
361}
362
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000363bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 if (effect1 == NULL)
365 effect1 = (SkDrawPathEffect*) child;
366 else
367 effect2 = (SkDrawPathEffect*) child;
368 return true;
369}
370
371SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
372 SkPathEffect* e1 = effect1->getPathEffect();
373 SkPathEffect* e2 = effect2->getPathEffect();
374 SkPathEffect* composite = new SkComposePathEffect(e1, e2);
375 e1->unref();
376 e2->unref();
377 return composite;
378}
379
380bool SkDrawComposePathEffect::isPaint() const {
381 return true;
382}
383
384//////////// SkDrawCornerPathEffect
385
386#if SK_USE_CONDENSED_INFO == 0
387
388const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
389 SK_MEMBER(radius, Float)
390};
391
392#endif
393
394DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
395
396SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
397 fType(type), radius(0) {
398}
399
400SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
401}
402
403SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
404 return new SkCornerPathEffect(radius);
405}
406
407/////////
408
409#include "SkExtras.h"
410
411const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
412const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
413const char kDrawComposePathEffectName[] = "pathEffect:compose";
414const char kDrawCornerPathEffectName[] = "pathEffect:corner";
415
416class SkExtraPathEffects : public SkExtras {
417public:
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000418 SkExtraPathEffects() :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419 skDrawShape1DPathEffectType(SkType_Unknown),
420 skDrawShape2DPathEffectType(SkType_Unknown),
421 skDrawComposePathEffectType(SkType_Unknown),
422 skDrawCornerPathEffectType(SkType_Unknown) {
423 }
reed@google.com82065d62011-02-07 15:30:46 +0000424
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425 virtual SkDisplayable* createInstance(SkDisplayTypes type) {
426 SkDisplayable* result = NULL;
427 if (skDrawShape1DPathEffectType == type)
428 result = new SkDrawShape1DPathEffect(type);
429 else if (skDrawShape2DPathEffectType == type)
430 result = new SkDrawShape2DPathEffect(type);
431 else if (skDrawComposePathEffectType == type)
432 result = new SkDrawComposePathEffect(type);
433 else if (skDrawCornerPathEffectType == type)
434 result = new SkDrawCornerPathEffect(type);
435 return result;
436 }
437
438 virtual bool definesType(SkDisplayTypes type) {
reed@google.com82065d62011-02-07 15:30:46 +0000439 return type == skDrawShape1DPathEffectType ||
440 type == skDrawShape2DPathEffectType ||
reed@android.com8a1c16f2008-12-17 15:59:43 +0000441 type == skDrawComposePathEffectType ||
442 type == skDrawCornerPathEffectType;
443 }
444
445#if SK_USE_CONDENSED_INFO == 0
446 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
447 const SkMemberInfo* info = NULL;
448 int infoCount = 0;
449 if (skDrawShape1DPathEffectType == type) {
450 info = SkDrawShape1DPathEffect::fInfo;
451 infoCount = SkDrawShape1DPathEffect::fInfoCount;
452 } else if (skDrawShape2DPathEffectType == type) {
453 info = SkDrawShape2DPathEffect::fInfo;
454 infoCount = SkDrawShape2DPathEffect::fInfoCount;
455 } else if (skDrawComposePathEffectType == type) {
456 info = SkDrawComposePathEffect::fInfo;
457 infoCount = SkDrawShape1DPathEffect::fInfoCount;
458 } else if (skDrawCornerPathEffectType == type) {
459 info = SkDrawCornerPathEffect::fInfo;
460 infoCount = SkDrawCornerPathEffect::fInfoCount;
461 }
462 if (infoCountPtr)
463 *infoCountPtr = infoCount;
464 return info;
465 }
466#endif
467
468#ifdef SK_DEBUG
469 virtual const char* getName(SkDisplayTypes type) {
470 if (skDrawShape1DPathEffectType == type)
471 return kDrawShape1DPathEffectName;
472 else if (skDrawShape2DPathEffectType == type)
473 return kDrawShape2DPathEffectName;
474 else if (skDrawComposePathEffectType == type)
475 return kDrawComposePathEffectName;
476 else if (skDrawCornerPathEffectType == type)
477 return kDrawCornerPathEffectName;
478 return NULL;
479 }
480#endif
481
482 virtual SkDisplayTypes getType(const char name[], size_t len ) {
483 SkDisplayTypes* type = NULL;
484 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
485 type = &skDrawShape1DPathEffectType;
486 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
487 type = &skDrawShape2DPathEffectType;
488 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
489 type = &skDrawComposePathEffectType;
490 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
491 type = &skDrawCornerPathEffectType;
492 if (type) {
493 if (*type == SkType_Unknown)
494 *type = SkDisplayType::RegisterNewType();
495 return *type;
496 }
497 return SkType_Unknown;
498 }
499
500private:
501 SkDisplayTypes skDrawShape1DPathEffectType;
502 SkDisplayTypes skDrawShape2DPathEffectType;
503 SkDisplayTypes skDrawComposePathEffectType;
504 SkDisplayTypes skDrawCornerPathEffectType;
505};
506
reed@android.com8a1c16f2008-12-17 15:59:43 +0000507void InitializeSkExtraPathEffects(SkAnimator* animator) {
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000508 animator->addExtras(new SkExtraPathEffects());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000509}
510
511////////////////
512
513
514SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
515}