blob: 007fb5263bd5021ab08f4edfa1c1e1266d5d0e80 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkDrawExtraPathEffect.h"
9#include "SkDrawPath.h"
10#include "Sk1DPathEffect.h"
11#include "Sk2DPathEffect.h"
12#include "SkMemberInfo.h"
reed@google.com8d4dc712014-04-18 15:14:25 +000013#include "SkPaintPart.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014#include "SkPathEffect.h"
15#include "SkCornerPathEffect.h"
16
17#include "SkDashPathEffect.h"
18
19class SkDrawShapePathEffect : public SkDrawPathEffect {
20 DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
21 SkDrawShapePathEffect();
22 virtual ~SkDrawShapePathEffect();
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000023 virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000024 virtual SkPathEffect* getPathEffect();
25protected:
26 SkDrawable* addPath;
27 SkDrawable* addMatrix;
28 SkDrawPath* path;
29 SkPathEffect* fPathEffect;
30 friend class SkShape1DPathEffect;
31 friend class SkShape2DPathEffect;
32};
33
34class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
35 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
36 SkDrawShape1DPathEffect(SkDisplayTypes );
37 virtual ~SkDrawShape1DPathEffect();
38 virtual void onEndElement(SkAnimateMaker& );
39private:
40 SkString phase;
41 SkString spacing;
42 friend class SkShape1DPathEffect;
43 typedef SkDrawShapePathEffect INHERITED;
44};
45
46class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
47 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
48 SkDrawShape2DPathEffect(SkDisplayTypes );
49 virtual ~SkDrawShape2DPathEffect();
50 virtual void onEndElement(SkAnimateMaker& );
51private:
52 SkDrawMatrix* matrix;
53 friend class SkShape2DPathEffect;
54 typedef SkDrawShapePathEffect INHERITED;
55};
56
57class SkDrawComposePathEffect : public SkDrawPathEffect {
58 DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect);
59 SkDrawComposePathEffect(SkDisplayTypes );
60 virtual ~SkDrawComposePathEffect();
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000061 virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE;
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 virtual SkPathEffect* getPathEffect();
reed@google.com82065d62011-02-07 15:30:46 +000063 virtual bool isPaint() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000064private:
65 SkDrawPathEffect* effect1;
66 SkDrawPathEffect* effect2;
67};
68
69class SkDrawCornerPathEffect : public SkDrawPathEffect {
70 DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
71 SkDrawCornerPathEffect(SkDisplayTypes );
72 virtual ~SkDrawCornerPathEffect();
73 virtual SkPathEffect* getPathEffect();
74private:
75 SkScalar radius;
76};
77
78//////////// SkShape1DPathEffect
79
80#include "SkAnimateMaker.h"
81#include "SkAnimatorScript.h"
82#include "SkDisplayApply.h"
83#include "SkDrawMatrix.h"
84#include "SkPaint.h"
85
86class SkShape1DPathEffect : public Sk1DPathEffect {
87public:
88 SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
89 fDraw(draw), fMaker(maker) {
90 }
91
djsollen@google.comba28d032012-03-26 17:57:35 +000092 SK_DECLARE_UNFLATTENABLE_OBJECT()
93
reed@android.com8a1c16f2008-12-17 15:59:43 +000094protected:
reed@google.com548a1f32012-12-18 16:12:09 +000095 virtual SkScalar begin(SkScalar contourLength) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 SkScriptValue value;
97 SkAnimatorScript engine(*fMaker, NULL, SkType_Float);
98 engine.propertyCallBack(GetContourLength, &contourLength);
99 value.fOperand.fScalar = 0;
100 engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float);
101 return value.fOperand.fScalar;
102 }
103
reed@google.com548a1f32012-12-18 16:12:09 +0000104 virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance);
106 SkDrawPath* drawPath = NULL;
107 if (fDraw->addPath->isPath()) {
108 drawPath = (SkDrawPath*) fDraw->addPath;
109 } else {
110 SkApply* apply = (SkApply*) fDraw->addPath;
111 apply->refresh(*fMaker);
112 apply->activate(*fMaker);
reed@google.com8015cdd2013-12-18 15:49:32 +0000113 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114 drawPath = (SkDrawPath*) apply->getScope();
115 }
116 SkMatrix m;
117 m.reset();
118 if (fDraw->addMatrix) {
119 SkDrawMatrix* matrix;
reed@google.com82065d62011-02-07 15:30:46 +0000120 if (fDraw->addMatrix->getType() == SkType_Matrix)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 matrix = (SkDrawMatrix*) fDraw->addMatrix;
122 else {
123 SkApply* apply = (SkApply*) fDraw->addMatrix;
124 apply->refresh(*fMaker);
125 apply->activate(*fMaker);
reed@google.com8015cdd2013-12-18 15:49:32 +0000126 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 matrix = (SkDrawMatrix*) apply->getScope();
128 }
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000129 if (matrix) {
130 m = matrix->getMatrix();
131 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 }
133 SkScalar result = 0;
134 SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result);
135 if (drawPath)
136 dst->addPath(drawPath->getPath(), m);
137 fMaker->clearExtraPropertyCallBack(fDraw->fType);
138 return result;
139 }
140
141private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142 static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) {
143 if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) {
144 value->fOperand.fScalar = *(SkScalar*) clen;
145 value->fType = SkType_Float;
146 return true;
147 }
148 return false;
149 }
150
151 static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) {
152 if (SK_LITERAL_STR_EQUAL("distance", token, len)) {
153 value->fOperand.fScalar = *(SkScalar*) dist;
154 value->fType = SkType_Float;
155 return true;
156 }
157 return false;
158 }
159
160 SkDrawShape1DPathEffect* fDraw;
161 SkAnimateMaker* fMaker;
162};
163
164//////////// SkDrawShapePathEffect
165
166#if SK_USE_CONDENSED_INFO == 0
167
168const SkMemberInfo SkDrawShapePathEffect::fInfo[] = {
169 SK_MEMBER(addMatrix, Drawable), // either matrix or apply
170 SK_MEMBER(addPath, Drawable), // either path or apply
171 SK_MEMBER(path, Path),
172};
173
174#endif
175
176DEFINE_GET_MEMBER(SkDrawShapePathEffect);
177
reed@google.com82065d62011-02-07 15:30:46 +0000178SkDrawShapePathEffect::SkDrawShapePathEffect() :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
180}
181
182SkDrawShapePathEffect::~SkDrawShapePathEffect() {
reed@google.com82065d62011-02-07 15:30:46 +0000183 SkSafeUnref(fPathEffect);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184}
185
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000186bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187 path = (SkDrawPath*) child;
188 return true;
189}
190
191SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
192 fPathEffect->ref();
193 return fPathEffect;
194}
195
196//////////// SkDrawShape1DPathEffect
197
198#if SK_USE_CONDENSED_INFO == 0
199
200const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
201 SK_MEMBER_INHERITED,
202 SK_MEMBER(phase, String),
203 SK_MEMBER(spacing, String),
204};
205
206#endif
207
208DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
209
210SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
211}
212
213SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
214}
215
216void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) {
217 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false))
218 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
219 else
220 fPathEffect = new SkShape1DPathEffect(this, &maker);
221}
222
223////////// SkShape2DPathEffect
224
225class SkShape2DPathEffect : public Sk2DPathEffect {
226public:
reed@google.com82065d62011-02-07 15:30:46 +0000227 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
229 }
230
231protected:
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000232 virtual void begin(const SkIRect& uvBounds, SkPath*) const SK_OVERRIDE {
233 const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
234 }
235
236 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE {
237 const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
238 }
239
240private:
241 void setUVBounds(const SkIRect& uvBounds) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
243 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
244 }
245
sugoi@google.comdfc867b2013-03-11 18:45:12 +0000246 void addPath(const SkPoint& loc, int u, int v, SkPath* dst) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247 fLoc = loc;
248 fU = u;
249 fV = v;
250 SkDrawPath* drawPath;
251 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
252 if (fDraw->addPath->isPath()) {
253 drawPath = (SkDrawPath*) fDraw->addPath;
254 } else {
255 SkApply* apply = (SkApply*) fDraw->addPath;
256 apply->refresh(*fMaker);
257 apply->activate(*fMaker);
258 apply->interpolate(*fMaker, v);
259 drawPath = (SkDrawPath*) apply->getScope();
260 }
261 if (drawPath == NULL)
262 goto clearCallBack;
263 if (fDraw->matrix) {
264 SkDrawMatrix* matrix;
reed@google.com82065d62011-02-07 15:30:46 +0000265 if (fDraw->matrix->getType() == SkType_Matrix)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266 matrix = (SkDrawMatrix*) fDraw->matrix;
267 else {
268 SkApply* apply = (SkApply*) fDraw->matrix;
269 apply->activate(*fMaker);
270 apply->interpolate(*fMaker, v);
271 matrix = (SkDrawMatrix*) apply->getScope();
272 }
273 if (matrix) {
274 dst->addPath(drawPath->getPath(), matrix->getMatrix());
275 goto clearCallBack;
276 }
277 }
278 dst->addPath(drawPath->getPath());
279clearCallBack:
280 fMaker->clearExtraPropertyCallBack(fDraw->fType);
281 }
282
reed@android.com8a1c16f2008-12-17 15:59:43 +0000283 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
284 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
285 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
286 int index;
287 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
288 return false;
289 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6);
290 if (index < 6) {
291 value->fType = SkType_Float;
292 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
293 } else {
294 value->fType = SkType_Int;
295 value->fOperand.fS32 = (&shape2D->fU)[index - 6];
296 }
297 return true;
298 }
reed@google.com82065d62011-02-07 15:30:46 +0000299
reed@android.com8a1c16f2008-12-17 15:59:43 +0000300 SkPoint fLoc;
301 SkRect fUVBounds;
302 int32_t fU;
303 int32_t fV;
304 SkDrawShape2DPathEffect* fDraw;
305 SkAnimateMaker* fMaker;
306
307 // illegal
308 SkShape2DPathEffect(const SkShape2DPathEffect&);
309 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
310};
311
312////////// SkDrawShape2DPathEffect
313
314#if SK_USE_CONDENSED_INFO == 0
315
316const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
317 SK_MEMBER_INHERITED,
318 SK_MEMBER(matrix, Matrix)
319};
320
321#endif
322
323DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
324
325SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
326}
327
328SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
329}
330
331void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
332 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
333 matrix == NULL)
334 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
335 else
336 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
337}
338
339////////// SkDrawComposePathEffect
340
341#if SK_USE_CONDENSED_INFO == 0
342
343const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
344 SK_MEMBER(effect1, PathEffect),
345 SK_MEMBER(effect2, PathEffect)
346};
347
348#endif
349
350DEFINE_GET_MEMBER(SkDrawComposePathEffect);
351
352SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
353 effect1(NULL), effect2(NULL) {
354}
355
356SkDrawComposePathEffect::~SkDrawComposePathEffect() {
357 delete effect1;
358 delete effect2;
359}
360
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +0000361bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 if (effect1 == NULL)
363 effect1 = (SkDrawPathEffect*) child;
364 else
365 effect2 = (SkDrawPathEffect*) child;
366 return true;
367}
368
369SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
370 SkPathEffect* e1 = effect1->getPathEffect();
371 SkPathEffect* e2 = effect2->getPathEffect();
commit-bot@chromium.org0a2bf902014-02-20 20:40:19 +0000372 SkPathEffect* composite = SkComposePathEffect::Create(e1, e2);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000373 e1->unref();
374 e2->unref();
375 return composite;
376}
377
378bool SkDrawComposePathEffect::isPaint() const {
379 return true;
380}
381
382//////////// SkDrawCornerPathEffect
383
384#if SK_USE_CONDENSED_INFO == 0
385
386const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
387 SK_MEMBER(radius, Float)
388};
389
390#endif
391
392DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
393
394SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
395 fType(type), radius(0) {
396}
397
398SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
399}
400
401SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
commit-bot@chromium.org0a2bf902014-02-20 20:40:19 +0000402 return SkCornerPathEffect::Create(radius);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000403}
404
405/////////
406
407#include "SkExtras.h"
408
409const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
410const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
411const char kDrawComposePathEffectName[] = "pathEffect:compose";
412const char kDrawCornerPathEffectName[] = "pathEffect:corner";
413
414class SkExtraPathEffects : public SkExtras {
415public:
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000416 SkExtraPathEffects() :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417 skDrawShape1DPathEffectType(SkType_Unknown),
418 skDrawShape2DPathEffectType(SkType_Unknown),
419 skDrawComposePathEffectType(SkType_Unknown),
420 skDrawCornerPathEffectType(SkType_Unknown) {
421 }
reed@google.com82065d62011-02-07 15:30:46 +0000422
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 virtual SkDisplayable* createInstance(SkDisplayTypes type) {
424 SkDisplayable* result = NULL;
425 if (skDrawShape1DPathEffectType == type)
426 result = new SkDrawShape1DPathEffect(type);
427 else if (skDrawShape2DPathEffectType == type)
428 result = new SkDrawShape2DPathEffect(type);
429 else if (skDrawComposePathEffectType == type)
430 result = new SkDrawComposePathEffect(type);
431 else if (skDrawCornerPathEffectType == type)
432 result = new SkDrawCornerPathEffect(type);
433 return result;
434 }
435
436 virtual bool definesType(SkDisplayTypes type) {
reed@google.com82065d62011-02-07 15:30:46 +0000437 return type == skDrawShape1DPathEffectType ||
438 type == skDrawShape2DPathEffectType ||
reed@android.com8a1c16f2008-12-17 15:59:43 +0000439 type == skDrawComposePathEffectType ||
440 type == skDrawCornerPathEffectType;
441 }
442
443#if SK_USE_CONDENSED_INFO == 0
444 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
445 const SkMemberInfo* info = NULL;
446 int infoCount = 0;
447 if (skDrawShape1DPathEffectType == type) {
448 info = SkDrawShape1DPathEffect::fInfo;
449 infoCount = SkDrawShape1DPathEffect::fInfoCount;
450 } else if (skDrawShape2DPathEffectType == type) {
451 info = SkDrawShape2DPathEffect::fInfo;
452 infoCount = SkDrawShape2DPathEffect::fInfoCount;
453 } else if (skDrawComposePathEffectType == type) {
454 info = SkDrawComposePathEffect::fInfo;
455 infoCount = SkDrawShape1DPathEffect::fInfoCount;
456 } else if (skDrawCornerPathEffectType == type) {
457 info = SkDrawCornerPathEffect::fInfo;
458 infoCount = SkDrawCornerPathEffect::fInfoCount;
459 }
460 if (infoCountPtr)
461 *infoCountPtr = infoCount;
462 return info;
463 }
464#endif
465
466#ifdef SK_DEBUG
467 virtual const char* getName(SkDisplayTypes type) {
468 if (skDrawShape1DPathEffectType == type)
469 return kDrawShape1DPathEffectName;
470 else if (skDrawShape2DPathEffectType == type)
471 return kDrawShape2DPathEffectName;
472 else if (skDrawComposePathEffectType == type)
473 return kDrawComposePathEffectName;
474 else if (skDrawCornerPathEffectType == type)
475 return kDrawCornerPathEffectName;
476 return NULL;
477 }
478#endif
479
480 virtual SkDisplayTypes getType(const char name[], size_t len ) {
481 SkDisplayTypes* type = NULL;
482 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
483 type = &skDrawShape1DPathEffectType;
484 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
485 type = &skDrawShape2DPathEffectType;
486 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
487 type = &skDrawComposePathEffectType;
488 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
489 type = &skDrawCornerPathEffectType;
490 if (type) {
491 if (*type == SkType_Unknown)
492 *type = SkDisplayType::RegisterNewType();
493 return *type;
494 }
495 return SkType_Unknown;
496 }
497
498private:
499 SkDisplayTypes skDrawShape1DPathEffectType;
500 SkDisplayTypes skDrawShape2DPathEffectType;
501 SkDisplayTypes skDrawComposePathEffectType;
502 SkDisplayTypes skDrawCornerPathEffectType;
503};
504
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505void InitializeSkExtraPathEffects(SkAnimator* animator) {
sugoi@google.com93c7ee32013-03-12 14:36:57 +0000506 animator->addExtras(new SkExtraPathEffects());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000507}
508
509////////////////
510
511
512SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {
513}