1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/animator/SkDrawExtraPathEffect.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,515 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkDrawExtraPathEffect.h" 1.14 +#include "SkDrawPath.h" 1.15 +#include "Sk1DPathEffect.h" 1.16 +#include "Sk2DPathEffect.h" 1.17 +#include "SkMemberInfo.h" 1.18 +#include "SkPaintParts.h" 1.19 +#include "SkPathEffect.h" 1.20 +#include "SkCornerPathEffect.h" 1.21 + 1.22 +#include "SkDashPathEffect.h" 1.23 + 1.24 +class SkDrawShapePathEffect : public SkDrawPathEffect { 1.25 + DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect); 1.26 + SkDrawShapePathEffect(); 1.27 + virtual ~SkDrawShapePathEffect(); 1.28 + virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE; 1.29 + virtual SkPathEffect* getPathEffect(); 1.30 +protected: 1.31 + SkDrawable* addPath; 1.32 + SkDrawable* addMatrix; 1.33 + SkDrawPath* path; 1.34 + SkPathEffect* fPathEffect; 1.35 + friend class SkShape1DPathEffect; 1.36 + friend class SkShape2DPathEffect; 1.37 +}; 1.38 + 1.39 +class SkDrawShape1DPathEffect : public SkDrawShapePathEffect { 1.40 + DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect); 1.41 + SkDrawShape1DPathEffect(SkDisplayTypes ); 1.42 + virtual ~SkDrawShape1DPathEffect(); 1.43 + virtual void onEndElement(SkAnimateMaker& ); 1.44 +private: 1.45 + SkString phase; 1.46 + SkString spacing; 1.47 + friend class SkShape1DPathEffect; 1.48 + typedef SkDrawShapePathEffect INHERITED; 1.49 +}; 1.50 + 1.51 +class SkDrawShape2DPathEffect : public SkDrawShapePathEffect { 1.52 + DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect); 1.53 + SkDrawShape2DPathEffect(SkDisplayTypes ); 1.54 + virtual ~SkDrawShape2DPathEffect(); 1.55 + virtual void onEndElement(SkAnimateMaker& ); 1.56 +private: 1.57 + SkDrawMatrix* matrix; 1.58 + friend class SkShape2DPathEffect; 1.59 + typedef SkDrawShapePathEffect INHERITED; 1.60 +}; 1.61 + 1.62 +class SkDrawComposePathEffect : public SkDrawPathEffect { 1.63 + DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect); 1.64 + SkDrawComposePathEffect(SkDisplayTypes ); 1.65 + virtual ~SkDrawComposePathEffect(); 1.66 + virtual bool addChild(SkAnimateMaker& , SkDisplayable* ) SK_OVERRIDE; 1.67 + virtual SkPathEffect* getPathEffect(); 1.68 + virtual bool isPaint() const; 1.69 +private: 1.70 + SkDrawPathEffect* effect1; 1.71 + SkDrawPathEffect* effect2; 1.72 +}; 1.73 + 1.74 +class SkDrawCornerPathEffect : public SkDrawPathEffect { 1.75 + DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect); 1.76 + SkDrawCornerPathEffect(SkDisplayTypes ); 1.77 + virtual ~SkDrawCornerPathEffect(); 1.78 + virtual SkPathEffect* getPathEffect(); 1.79 +private: 1.80 + SkScalar radius; 1.81 +}; 1.82 + 1.83 +//////////// SkShape1DPathEffect 1.84 + 1.85 +#include "SkAnimateMaker.h" 1.86 +#include "SkAnimatorScript.h" 1.87 +#include "SkDisplayApply.h" 1.88 +#include "SkDrawMatrix.h" 1.89 +#include "SkPaint.h" 1.90 + 1.91 +class SkShape1DPathEffect : public Sk1DPathEffect { 1.92 +public: 1.93 + SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) : 1.94 + fDraw(draw), fMaker(maker) { 1.95 + } 1.96 + 1.97 + SK_DECLARE_UNFLATTENABLE_OBJECT() 1.98 + 1.99 +protected: 1.100 + virtual SkScalar begin(SkScalar contourLength) const { 1.101 + SkScriptValue value; 1.102 + SkAnimatorScript engine(*fMaker, NULL, SkType_Float); 1.103 + engine.propertyCallBack(GetContourLength, &contourLength); 1.104 + value.fOperand.fScalar = 0; 1.105 + engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float); 1.106 + return value.fOperand.fScalar; 1.107 + } 1.108 + 1.109 + virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const { 1.110 + fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance); 1.111 + SkDrawPath* drawPath = NULL; 1.112 + if (fDraw->addPath->isPath()) { 1.113 + drawPath = (SkDrawPath*) fDraw->addPath; 1.114 + } else { 1.115 + SkApply* apply = (SkApply*) fDraw->addPath; 1.116 + apply->refresh(*fMaker); 1.117 + apply->activate(*fMaker); 1.118 + apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000)); 1.119 + drawPath = (SkDrawPath*) apply->getScope(); 1.120 + } 1.121 + SkMatrix m; 1.122 + m.reset(); 1.123 + if (fDraw->addMatrix) { 1.124 + SkDrawMatrix* matrix; 1.125 + if (fDraw->addMatrix->getType() == SkType_Matrix) 1.126 + matrix = (SkDrawMatrix*) fDraw->addMatrix; 1.127 + else { 1.128 + SkApply* apply = (SkApply*) fDraw->addMatrix; 1.129 + apply->refresh(*fMaker); 1.130 + apply->activate(*fMaker); 1.131 + apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000)); 1.132 + matrix = (SkDrawMatrix*) apply->getScope(); 1.133 + } 1.134 + if (matrix) { 1.135 + m = matrix->getMatrix(); 1.136 + } 1.137 + } 1.138 + SkScalar result = 0; 1.139 + SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result); 1.140 + if (drawPath) 1.141 + dst->addPath(drawPath->getPath(), m); 1.142 + fMaker->clearExtraPropertyCallBack(fDraw->fType); 1.143 + return result; 1.144 + } 1.145 + 1.146 +private: 1.147 + static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) { 1.148 + if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) { 1.149 + value->fOperand.fScalar = *(SkScalar*) clen; 1.150 + value->fType = SkType_Float; 1.151 + return true; 1.152 + } 1.153 + return false; 1.154 + } 1.155 + 1.156 + static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) { 1.157 + if (SK_LITERAL_STR_EQUAL("distance", token, len)) { 1.158 + value->fOperand.fScalar = *(SkScalar*) dist; 1.159 + value->fType = SkType_Float; 1.160 + return true; 1.161 + } 1.162 + return false; 1.163 + } 1.164 + 1.165 + SkDrawShape1DPathEffect* fDraw; 1.166 + SkAnimateMaker* fMaker; 1.167 +}; 1.168 + 1.169 +//////////// SkDrawShapePathEffect 1.170 + 1.171 +#if SK_USE_CONDENSED_INFO == 0 1.172 + 1.173 +const SkMemberInfo SkDrawShapePathEffect::fInfo[] = { 1.174 + SK_MEMBER(addMatrix, Drawable), // either matrix or apply 1.175 + SK_MEMBER(addPath, Drawable), // either path or apply 1.176 + SK_MEMBER(path, Path), 1.177 +}; 1.178 + 1.179 +#endif 1.180 + 1.181 +DEFINE_GET_MEMBER(SkDrawShapePathEffect); 1.182 + 1.183 +SkDrawShapePathEffect::SkDrawShapePathEffect() : 1.184 + addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) { 1.185 +} 1.186 + 1.187 +SkDrawShapePathEffect::~SkDrawShapePathEffect() { 1.188 + SkSafeUnref(fPathEffect); 1.189 +} 1.190 + 1.191 +bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) { 1.192 + path = (SkDrawPath*) child; 1.193 + return true; 1.194 +} 1.195 + 1.196 +SkPathEffect* SkDrawShapePathEffect::getPathEffect() { 1.197 + fPathEffect->ref(); 1.198 + return fPathEffect; 1.199 +} 1.200 + 1.201 +//////////// SkDrawShape1DPathEffect 1.202 + 1.203 +#if SK_USE_CONDENSED_INFO == 0 1.204 + 1.205 +const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = { 1.206 + SK_MEMBER_INHERITED, 1.207 + SK_MEMBER(phase, String), 1.208 + SK_MEMBER(spacing, String), 1.209 +}; 1.210 + 1.211 +#endif 1.212 + 1.213 +DEFINE_GET_MEMBER(SkDrawShape1DPathEffect); 1.214 + 1.215 +SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) { 1.216 +} 1.217 + 1.218 +SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() { 1.219 +} 1.220 + 1.221 +void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) { 1.222 + if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false)) 1.223 + maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error 1.224 + else 1.225 + fPathEffect = new SkShape1DPathEffect(this, &maker); 1.226 +} 1.227 + 1.228 +////////// SkShape2DPathEffect 1.229 + 1.230 +class SkShape2DPathEffect : public Sk2DPathEffect { 1.231 +public: 1.232 + SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker, 1.233 + const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) { 1.234 + } 1.235 + 1.236 +protected: 1.237 + virtual void begin(const SkIRect& uvBounds, SkPath*) const SK_OVERRIDE { 1.238 + const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds); 1.239 + } 1.240 + 1.241 + virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const SK_OVERRIDE { 1.242 + const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst); 1.243 + } 1.244 + 1.245 +private: 1.246 + void setUVBounds(const SkIRect& uvBounds) { 1.247 + fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop), 1.248 + SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom)); 1.249 + } 1.250 + 1.251 + void addPath(const SkPoint& loc, int u, int v, SkPath* dst) { 1.252 + fLoc = loc; 1.253 + fU = u; 1.254 + fV = v; 1.255 + SkDrawPath* drawPath; 1.256 + fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this); 1.257 + if (fDraw->addPath->isPath()) { 1.258 + drawPath = (SkDrawPath*) fDraw->addPath; 1.259 + } else { 1.260 + SkApply* apply = (SkApply*) fDraw->addPath; 1.261 + apply->refresh(*fMaker); 1.262 + apply->activate(*fMaker); 1.263 + apply->interpolate(*fMaker, v); 1.264 + drawPath = (SkDrawPath*) apply->getScope(); 1.265 + } 1.266 + if (drawPath == NULL) 1.267 + goto clearCallBack; 1.268 + if (fDraw->matrix) { 1.269 + SkDrawMatrix* matrix; 1.270 + if (fDraw->matrix->getType() == SkType_Matrix) 1.271 + matrix = (SkDrawMatrix*) fDraw->matrix; 1.272 + else { 1.273 + SkApply* apply = (SkApply*) fDraw->matrix; 1.274 + apply->activate(*fMaker); 1.275 + apply->interpolate(*fMaker, v); 1.276 + matrix = (SkDrawMatrix*) apply->getScope(); 1.277 + } 1.278 + if (matrix) { 1.279 + dst->addPath(drawPath->getPath(), matrix->getMatrix()); 1.280 + goto clearCallBack; 1.281 + } 1.282 + } 1.283 + dst->addPath(drawPath->getPath()); 1.284 +clearCallBack: 1.285 + fMaker->clearExtraPropertyCallBack(fDraw->fType); 1.286 + } 1.287 + 1.288 + static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) { 1.289 + static const char match[] = "locX|locY|left|top|right|bottom|u|v" ; 1.290 + SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D; 1.291 + int index; 1.292 + if (SkAnimatorScript::MapEnums(match, token, len, &index) == false) 1.293 + return false; 1.294 + SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6); 1.295 + if (index < 6) { 1.296 + value->fType = SkType_Float; 1.297 + value->fOperand.fScalar = (&shape2D->fLoc.fX)[index]; 1.298 + } else { 1.299 + value->fType = SkType_Int; 1.300 + value->fOperand.fS32 = (&shape2D->fU)[index - 6]; 1.301 + } 1.302 + return true; 1.303 + } 1.304 + 1.305 + SkPoint fLoc; 1.306 + SkRect fUVBounds; 1.307 + int32_t fU; 1.308 + int32_t fV; 1.309 + SkDrawShape2DPathEffect* fDraw; 1.310 + SkAnimateMaker* fMaker; 1.311 + 1.312 + // illegal 1.313 + SkShape2DPathEffect(const SkShape2DPathEffect&); 1.314 + SkShape2DPathEffect& operator=(const SkShape2DPathEffect&); 1.315 +}; 1.316 + 1.317 +////////// SkDrawShape2DPathEffect 1.318 + 1.319 +#if SK_USE_CONDENSED_INFO == 0 1.320 + 1.321 +const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = { 1.322 + SK_MEMBER_INHERITED, 1.323 + SK_MEMBER(matrix, Matrix) 1.324 +}; 1.325 + 1.326 +#endif 1.327 + 1.328 +DEFINE_GET_MEMBER(SkDrawShape2DPathEffect); 1.329 + 1.330 +SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) { 1.331 +} 1.332 + 1.333 +SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() { 1.334 +} 1.335 + 1.336 +void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) { 1.337 + if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) || 1.338 + matrix == NULL) 1.339 + maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error 1.340 + else 1.341 + fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix()); 1.342 +} 1.343 + 1.344 +////////// SkDrawComposePathEffect 1.345 + 1.346 +#if SK_USE_CONDENSED_INFO == 0 1.347 + 1.348 +const SkMemberInfo SkDrawComposePathEffect::fInfo[] = { 1.349 + SK_MEMBER(effect1, PathEffect), 1.350 + SK_MEMBER(effect2, PathEffect) 1.351 +}; 1.352 + 1.353 +#endif 1.354 + 1.355 +DEFINE_GET_MEMBER(SkDrawComposePathEffect); 1.356 + 1.357 +SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type), 1.358 + effect1(NULL), effect2(NULL) { 1.359 +} 1.360 + 1.361 +SkDrawComposePathEffect::~SkDrawComposePathEffect() { 1.362 + delete effect1; 1.363 + delete effect2; 1.364 +} 1.365 + 1.366 +bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) { 1.367 + if (effect1 == NULL) 1.368 + effect1 = (SkDrawPathEffect*) child; 1.369 + else 1.370 + effect2 = (SkDrawPathEffect*) child; 1.371 + return true; 1.372 +} 1.373 + 1.374 +SkPathEffect* SkDrawComposePathEffect::getPathEffect() { 1.375 + SkPathEffect* e1 = effect1->getPathEffect(); 1.376 + SkPathEffect* e2 = effect2->getPathEffect(); 1.377 + SkPathEffect* composite = SkComposePathEffect::Create(e1, e2); 1.378 + e1->unref(); 1.379 + e2->unref(); 1.380 + return composite; 1.381 +} 1.382 + 1.383 +bool SkDrawComposePathEffect::isPaint() const { 1.384 + return true; 1.385 +} 1.386 + 1.387 +//////////// SkDrawCornerPathEffect 1.388 + 1.389 +#if SK_USE_CONDENSED_INFO == 0 1.390 + 1.391 +const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = { 1.392 + SK_MEMBER(radius, Float) 1.393 +}; 1.394 + 1.395 +#endif 1.396 + 1.397 +DEFINE_GET_MEMBER(SkDrawCornerPathEffect); 1.398 + 1.399 +SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type): 1.400 + fType(type), radius(0) { 1.401 +} 1.402 + 1.403 +SkDrawCornerPathEffect::~SkDrawCornerPathEffect() { 1.404 +} 1.405 + 1.406 +SkPathEffect* SkDrawCornerPathEffect::getPathEffect() { 1.407 + return SkCornerPathEffect::Create(radius); 1.408 +} 1.409 + 1.410 +///////// 1.411 + 1.412 +#include "SkExtras.h" 1.413 + 1.414 +const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D"; 1.415 +const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D"; 1.416 +const char kDrawComposePathEffectName[] = "pathEffect:compose"; 1.417 +const char kDrawCornerPathEffectName[] = "pathEffect:corner"; 1.418 + 1.419 +class SkExtraPathEffects : public SkExtras { 1.420 +public: 1.421 + SkExtraPathEffects() : 1.422 + skDrawShape1DPathEffectType(SkType_Unknown), 1.423 + skDrawShape2DPathEffectType(SkType_Unknown), 1.424 + skDrawComposePathEffectType(SkType_Unknown), 1.425 + skDrawCornerPathEffectType(SkType_Unknown) { 1.426 + } 1.427 + 1.428 + virtual SkDisplayable* createInstance(SkDisplayTypes type) { 1.429 + SkDisplayable* result = NULL; 1.430 + if (skDrawShape1DPathEffectType == type) 1.431 + result = new SkDrawShape1DPathEffect(type); 1.432 + else if (skDrawShape2DPathEffectType == type) 1.433 + result = new SkDrawShape2DPathEffect(type); 1.434 + else if (skDrawComposePathEffectType == type) 1.435 + result = new SkDrawComposePathEffect(type); 1.436 + else if (skDrawCornerPathEffectType == type) 1.437 + result = new SkDrawCornerPathEffect(type); 1.438 + return result; 1.439 + } 1.440 + 1.441 + virtual bool definesType(SkDisplayTypes type) { 1.442 + return type == skDrawShape1DPathEffectType || 1.443 + type == skDrawShape2DPathEffectType || 1.444 + type == skDrawComposePathEffectType || 1.445 + type == skDrawCornerPathEffectType; 1.446 + } 1.447 + 1.448 +#if SK_USE_CONDENSED_INFO == 0 1.449 + virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) { 1.450 + const SkMemberInfo* info = NULL; 1.451 + int infoCount = 0; 1.452 + if (skDrawShape1DPathEffectType == type) { 1.453 + info = SkDrawShape1DPathEffect::fInfo; 1.454 + infoCount = SkDrawShape1DPathEffect::fInfoCount; 1.455 + } else if (skDrawShape2DPathEffectType == type) { 1.456 + info = SkDrawShape2DPathEffect::fInfo; 1.457 + infoCount = SkDrawShape2DPathEffect::fInfoCount; 1.458 + } else if (skDrawComposePathEffectType == type) { 1.459 + info = SkDrawComposePathEffect::fInfo; 1.460 + infoCount = SkDrawShape1DPathEffect::fInfoCount; 1.461 + } else if (skDrawCornerPathEffectType == type) { 1.462 + info = SkDrawCornerPathEffect::fInfo; 1.463 + infoCount = SkDrawCornerPathEffect::fInfoCount; 1.464 + } 1.465 + if (infoCountPtr) 1.466 + *infoCountPtr = infoCount; 1.467 + return info; 1.468 + } 1.469 +#endif 1.470 + 1.471 +#ifdef SK_DEBUG 1.472 + virtual const char* getName(SkDisplayTypes type) { 1.473 + if (skDrawShape1DPathEffectType == type) 1.474 + return kDrawShape1DPathEffectName; 1.475 + else if (skDrawShape2DPathEffectType == type) 1.476 + return kDrawShape2DPathEffectName; 1.477 + else if (skDrawComposePathEffectType == type) 1.478 + return kDrawComposePathEffectName; 1.479 + else if (skDrawCornerPathEffectType == type) 1.480 + return kDrawCornerPathEffectName; 1.481 + return NULL; 1.482 + } 1.483 +#endif 1.484 + 1.485 + virtual SkDisplayTypes getType(const char name[], size_t len ) { 1.486 + SkDisplayTypes* type = NULL; 1.487 + if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len)) 1.488 + type = &skDrawShape1DPathEffectType; 1.489 + else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len)) 1.490 + type = &skDrawShape2DPathEffectType; 1.491 + else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len)) 1.492 + type = &skDrawComposePathEffectType; 1.493 + else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len)) 1.494 + type = &skDrawCornerPathEffectType; 1.495 + if (type) { 1.496 + if (*type == SkType_Unknown) 1.497 + *type = SkDisplayType::RegisterNewType(); 1.498 + return *type; 1.499 + } 1.500 + return SkType_Unknown; 1.501 + } 1.502 + 1.503 +private: 1.504 + SkDisplayTypes skDrawShape1DPathEffectType; 1.505 + SkDisplayTypes skDrawShape2DPathEffectType; 1.506 + SkDisplayTypes skDrawComposePathEffectType; 1.507 + SkDisplayTypes skDrawCornerPathEffectType; 1.508 +}; 1.509 + 1.510 +void InitializeSkExtraPathEffects(SkAnimator* animator) { 1.511 + animator->addExtras(new SkExtraPathEffects()); 1.512 +} 1.513 + 1.514 +//////////////// 1.515 + 1.516 + 1.517 +SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) { 1.518 +}