2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkDrawExtraPathEffect.h"
9 #include "SkDrawPath.h"
10 #include "Sk1DPathEffect.h"
11 #include "Sk2DPathEffect.h"
12 #include "SkMemberInfo.h"
13 #include "SkPaintPart.h"
14 #include "SkPathEffect.h"
15 #include "SkCornerPathEffect.h"
17 #include "SkDashPathEffect.h"
19 class SkDrawShapePathEffect : public SkDrawPathEffect {
20 DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
21 SkDrawShapePathEffect();
22 virtual ~SkDrawShapePathEffect();
23 bool addChild(SkAnimateMaker& , SkDisplayable* ) override;
24 SkPathEffect* getPathEffect() override;
27 SkADrawable* addMatrix;
29 SkPathEffect* fPathEffect;
30 friend class SkShape1DPathEffect;
31 friend class SkShape2DPathEffect;
34 class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
35 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
36 SkDrawShape1DPathEffect(SkDisplayTypes );
37 virtual ~SkDrawShape1DPathEffect();
38 void onEndElement(SkAnimateMaker& ) override;
42 friend class SkShape1DPathEffect;
43 typedef SkDrawShapePathEffect INHERITED;
46 class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
47 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
48 SkDrawShape2DPathEffect(SkDisplayTypes );
49 virtual ~SkDrawShape2DPathEffect();
50 void onEndElement(SkAnimateMaker& ) override;
53 friend class SkShape2DPathEffect;
54 typedef SkDrawShapePathEffect INHERITED;
57 class SkDrawComposePathEffect : public SkDrawPathEffect {
58 DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect);
59 SkDrawComposePathEffect(SkDisplayTypes );
60 virtual ~SkDrawComposePathEffect();
61 bool addChild(SkAnimateMaker& , SkDisplayable* ) override;
62 SkPathEffect* getPathEffect() override;
63 bool isPaint() const override;
65 SkDrawPathEffect* effect1;
66 SkDrawPathEffect* effect2;
69 class SkDrawCornerPathEffect : public SkDrawPathEffect {
70 DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
71 SkDrawCornerPathEffect(SkDisplayTypes );
72 virtual ~SkDrawCornerPathEffect();
73 SkPathEffect* getPathEffect() override;
78 //////////// SkShape1DPathEffect
80 #include "SkAnimateMaker.h"
81 #include "SkAnimatorScript.h"
82 #include "SkDisplayApply.h"
83 #include "SkDrawMatrix.h"
86 class SkShape1DPathEffect : public Sk1DPathEffect {
88 SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
89 fDraw(draw), fMaker(maker) {
92 // For serialization. This will never be called.
93 Factory getFactory() const override { sk_throw(); return NULL; }
96 SkScalar begin(SkScalar contourLength) const override {
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;
105 SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const override {
106 fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance);
107 SkDrawPath* drawPath = NULL;
108 if (fDraw->addPath->isPath()) {
109 drawPath = (SkDrawPath*) fDraw->addPath;
111 SkApply* apply = (SkApply*) fDraw->addPath;
112 apply->refresh(*fMaker);
113 apply->activate(*fMaker);
114 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
115 drawPath = (SkDrawPath*) apply->getScope();
119 if (fDraw->addMatrix) {
120 SkDrawMatrix* matrix;
121 if (fDraw->addMatrix->getType() == SkType_Matrix)
122 matrix = (SkDrawMatrix*) fDraw->addMatrix;
124 SkApply* apply = (SkApply*) fDraw->addMatrix;
125 apply->refresh(*fMaker);
126 apply->activate(*fMaker);
127 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
128 matrix = (SkDrawMatrix*) apply->getScope();
131 m = matrix->getMatrix();
135 SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result);
137 dst->addPath(drawPath->getPath(), m);
138 fMaker->clearExtraPropertyCallBack(fDraw->fType);
142 #ifndef SK_IGNORE_TO_STRING
143 void toString(SkString* str) const override {
144 str->appendf("SkShape1DPathEffect: (");
151 static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) {
152 if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) {
153 value->fOperand.fScalar = *(SkScalar*) clen;
154 value->fType = SkType_Float;
160 static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) {
161 if (SK_LITERAL_STR_EQUAL("distance", token, len)) {
162 value->fOperand.fScalar = *(SkScalar*) dist;
163 value->fType = SkType_Float;
169 SkDrawShape1DPathEffect* fDraw;
170 SkAnimateMaker* fMaker;
173 //////////// SkDrawShapePathEffect
175 #if SK_USE_CONDENSED_INFO == 0
177 const SkMemberInfo SkDrawShapePathEffect::fInfo[] = {
178 SK_MEMBER(addMatrix, Drawable), // either matrix or apply
179 SK_MEMBER(addPath, Drawable), // either path or apply
180 SK_MEMBER(path, Path),
185 DEFINE_GET_MEMBER(SkDrawShapePathEffect);
187 SkDrawShapePathEffect::SkDrawShapePathEffect() :
188 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) {
191 SkDrawShapePathEffect::~SkDrawShapePathEffect() {
192 SkSafeUnref(fPathEffect);
195 bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
196 path = (SkDrawPath*) child;
200 SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
205 //////////// SkDrawShape1DPathEffect
207 #if SK_USE_CONDENSED_INFO == 0
209 const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
211 SK_MEMBER(phase, String),
212 SK_MEMBER(spacing, String),
217 DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
219 SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
222 SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
225 void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) {
226 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false))
227 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
229 fPathEffect = new SkShape1DPathEffect(this, &maker);
232 ////////// SkShape2DPathEffect
234 class SkShape2DPathEffect : public Sk2DPathEffect {
236 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
237 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
240 // For serialization. This will never be called.
241 Factory getFactory() const override { sk_throw(); return NULL; }
244 void begin(const SkIRect& uvBounds, SkPath*) const override {
245 const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
248 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
249 const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
253 void setUVBounds(const SkIRect& uvBounds) {
254 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
255 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
258 void addPath(const SkPoint& loc, int u, int v, SkPath* dst) {
262 SkDrawPath* drawPath;
263 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
264 if (fDraw->addPath->isPath()) {
265 drawPath = (SkDrawPath*) fDraw->addPath;
267 SkApply* apply = (SkApply*) fDraw->addPath;
268 apply->refresh(*fMaker);
269 apply->activate(*fMaker);
270 apply->interpolate(*fMaker, v);
271 drawPath = (SkDrawPath*) apply->getScope();
273 if (drawPath == NULL)
276 SkDrawMatrix* matrix;
277 if (fDraw->matrix->getType() == SkType_Matrix)
278 matrix = (SkDrawMatrix*) fDraw->matrix;
280 SkApply* apply = (SkApply*) fDraw->matrix;
281 apply->activate(*fMaker);
282 apply->interpolate(*fMaker, v);
283 matrix = (SkDrawMatrix*) apply->getScope();
286 dst->addPath(drawPath->getPath(), matrix->getMatrix());
290 dst->addPath(drawPath->getPath());
292 fMaker->clearExtraPropertyCallBack(fDraw->fType);
295 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
296 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
297 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
299 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
301 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6);
303 value->fType = SkType_Float;
304 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
306 value->fType = SkType_Int;
307 value->fOperand.fS32 = (&shape2D->fU)[index - 6];
316 SkDrawShape2DPathEffect* fDraw;
317 SkAnimateMaker* fMaker;
320 SkShape2DPathEffect(const SkShape2DPathEffect&);
321 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
324 ////////// SkDrawShape2DPathEffect
326 #if SK_USE_CONDENSED_INFO == 0
328 const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
330 SK_MEMBER(matrix, Matrix)
335 DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
337 SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
340 SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
343 void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
344 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) ||
346 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
348 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
351 ////////// SkDrawComposePathEffect
353 #if SK_USE_CONDENSED_INFO == 0
355 const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
356 SK_MEMBER(effect1, PathEffect),
357 SK_MEMBER(effect2, PathEffect)
362 DEFINE_GET_MEMBER(SkDrawComposePathEffect);
364 SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
365 effect1(NULL), effect2(NULL) {
368 SkDrawComposePathEffect::~SkDrawComposePathEffect() {
373 bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
375 effect1 = (SkDrawPathEffect*) child;
377 effect2 = (SkDrawPathEffect*) child;
381 SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
382 SkPathEffect* e1 = effect1->getPathEffect();
383 SkPathEffect* e2 = effect2->getPathEffect();
384 SkPathEffect* composite = SkComposePathEffect::Create(e1, e2);
390 bool SkDrawComposePathEffect::isPaint() const {
394 //////////// SkDrawCornerPathEffect
396 #if SK_USE_CONDENSED_INFO == 0
398 const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
399 SK_MEMBER(radius, Float)
404 DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
406 SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
407 fType(type), radius(0) {
410 SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
413 SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
414 return SkCornerPathEffect::Create(radius);
419 #include "SkExtras.h"
421 const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
422 const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
423 const char kDrawComposePathEffectName[] = "pathEffect:compose";
424 const char kDrawCornerPathEffectName[] = "pathEffect:corner";
426 class SkExtraPathEffects : public SkExtras {
428 SkExtraPathEffects() :
429 skDrawShape1DPathEffectType(SkType_Unknown),
430 skDrawShape2DPathEffectType(SkType_Unknown),
431 skDrawComposePathEffectType(SkType_Unknown),
432 skDrawCornerPathEffectType(SkType_Unknown) {
435 virtual SkDisplayable* createInstance(SkDisplayTypes type) {
436 SkDisplayable* result = NULL;
437 if (skDrawShape1DPathEffectType == type)
438 result = new SkDrawShape1DPathEffect(type);
439 else if (skDrawShape2DPathEffectType == type)
440 result = new SkDrawShape2DPathEffect(type);
441 else if (skDrawComposePathEffectType == type)
442 result = new SkDrawComposePathEffect(type);
443 else if (skDrawCornerPathEffectType == type)
444 result = new SkDrawCornerPathEffect(type);
448 virtual bool definesType(SkDisplayTypes type) {
449 return type == skDrawShape1DPathEffectType ||
450 type == skDrawShape2DPathEffectType ||
451 type == skDrawComposePathEffectType ||
452 type == skDrawCornerPathEffectType;
455 #if SK_USE_CONDENSED_INFO == 0
456 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
457 const SkMemberInfo* info = NULL;
459 if (skDrawShape1DPathEffectType == type) {
460 info = SkDrawShape1DPathEffect::fInfo;
461 infoCount = SkDrawShape1DPathEffect::fInfoCount;
462 } else if (skDrawShape2DPathEffectType == type) {
463 info = SkDrawShape2DPathEffect::fInfo;
464 infoCount = SkDrawShape2DPathEffect::fInfoCount;
465 } else if (skDrawComposePathEffectType == type) {
466 info = SkDrawComposePathEffect::fInfo;
467 infoCount = SkDrawShape1DPathEffect::fInfoCount;
468 } else if (skDrawCornerPathEffectType == type) {
469 info = SkDrawCornerPathEffect::fInfo;
470 infoCount = SkDrawCornerPathEffect::fInfoCount;
473 *infoCountPtr = infoCount;
479 virtual const char* getName(SkDisplayTypes type) {
480 if (skDrawShape1DPathEffectType == type)
481 return kDrawShape1DPathEffectName;
482 else if (skDrawShape2DPathEffectType == type)
483 return kDrawShape2DPathEffectName;
484 else if (skDrawComposePathEffectType == type)
485 return kDrawComposePathEffectName;
486 else if (skDrawCornerPathEffectType == type)
487 return kDrawCornerPathEffectName;
492 virtual SkDisplayTypes getType(const char name[], size_t len ) {
493 SkDisplayTypes* type = NULL;
494 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
495 type = &skDrawShape1DPathEffectType;
496 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
497 type = &skDrawShape2DPathEffectType;
498 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
499 type = &skDrawComposePathEffectType;
500 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
501 type = &skDrawCornerPathEffectType;
503 if (*type == SkType_Unknown)
504 *type = SkDisplayType::RegisterNewType();
507 return SkType_Unknown;
511 SkDisplayTypes skDrawShape1DPathEffectType;
512 SkDisplayTypes skDrawShape2DPathEffectType;
513 SkDisplayTypes skDrawComposePathEffectType;
514 SkDisplayTypes skDrawCornerPathEffectType;
517 void InitializeSkExtraPathEffects(SkAnimator* animator) {
518 animator->addExtras(new SkExtraPathEffects());
524 SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) {