1/* libs/graphics/animator/SkDrawExtraPathEffect.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkDrawExtraPathEffect.h" 19#include "SkDrawPath.h" 20#include "Sk1DPathEffect.h" 21#include "Sk2DPathEffect.h" 22#include "SkMemberInfo.h" 23#include "SkPaintParts.h" 24#include "SkPathEffect.h" 25#include "SkCornerPathEffect.h" 26 27#include "SkDashPathEffect.h" 28 29class SkDrawShapePathEffect : public SkDrawPathEffect { 30 DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect); 31 SkDrawShapePathEffect(); 32 virtual ~SkDrawShapePathEffect(); 33 virtual bool add(SkAnimateMaker& , SkDisplayable* ); 34 virtual SkPathEffect* getPathEffect(); 35protected: 36 SkDrawable* addPath; 37 SkDrawable* addMatrix; 38 SkDrawPath* path; 39 SkPathEffect* fPathEffect; 40 friend class SkShape1DPathEffect; 41 friend class SkShape2DPathEffect; 42}; 43 44class SkDrawShape1DPathEffect : public SkDrawShapePathEffect { 45 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect); 46 SkDrawShape1DPathEffect(SkDisplayTypes ); 47 virtual ~SkDrawShape1DPathEffect(); 48 virtual void onEndElement(SkAnimateMaker& ); 49private: 50 SkString phase; 51 SkString spacing; 52 friend class SkShape1DPathEffect; 53 typedef SkDrawShapePathEffect INHERITED; 54}; 55 56class SkDrawShape2DPathEffect : public SkDrawShapePathEffect { 57 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect); 58 SkDrawShape2DPathEffect(SkDisplayTypes ); 59 virtual ~SkDrawShape2DPathEffect(); 60 virtual void onEndElement(SkAnimateMaker& ); 61private: 62 SkDrawMatrix* matrix; 63 friend class SkShape2DPathEffect; 64 typedef SkDrawShapePathEffect INHERITED; 65}; 66 67class SkDrawComposePathEffect : public SkDrawPathEffect { 68 DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect); 69 SkDrawComposePathEffect(SkDisplayTypes ); 70 virtual ~SkDrawComposePathEffect(); 71 virtual bool add(SkAnimateMaker& , SkDisplayable* ); 72 virtual SkPathEffect* getPathEffect(); 73 virtual bool isPaint() const; 74private: 75 SkDrawPathEffect* effect1; 76 SkDrawPathEffect* effect2; 77}; 78 79class SkDrawCornerPathEffect : public SkDrawPathEffect { 80 DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect); 81 SkDrawCornerPathEffect(SkDisplayTypes ); 82 virtual ~SkDrawCornerPathEffect(); 83 virtual SkPathEffect* getPathEffect(); 84private: 85 SkScalar radius; 86}; 87 88//////////// SkShape1DPathEffect 89 90#include "SkAnimateMaker.h" 91#include "SkAnimatorScript.h" 92#include "SkDisplayApply.h" 93#include "SkDrawMatrix.h" 94#include "SkPaint.h" 95 96class SkShape1DPathEffect : public Sk1DPathEffect { 97public: 98 SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) : 99 fDraw(draw), fMaker(maker) { 100 } 101 102protected: 103 virtual SkScalar begin(SkScalar contourLength) 104 { 105 SkScriptValue value; 106 SkAnimatorScript engine(*fMaker, NULL, SkType_Float); 107 engine.propertyCallBack(GetContourLength, &contourLength); 108 value.fOperand.fScalar = 0; 109 engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float); 110 return value.fOperand.fScalar; 111 } 112 113 virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure& ) 114 { 115 fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance); 116 SkDrawPath* drawPath = NULL; 117 if (fDraw->addPath->isPath()) { 118 drawPath = (SkDrawPath*) fDraw->addPath; 119 } else { 120 SkApply* apply = (SkApply*) fDraw->addPath; 121 apply->refresh(*fMaker); 122 apply->activate(*fMaker); 123 apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000)); 124 drawPath = (SkDrawPath*) apply->getScope(); 125 } 126 SkMatrix m; 127 m.reset(); 128 if (fDraw->addMatrix) { 129 SkDrawMatrix* matrix; 130 if (fDraw->addMatrix->getType() == SkType_Matrix) 131 matrix = (SkDrawMatrix*) fDraw->addMatrix; 132 else { 133 SkApply* apply = (SkApply*) fDraw->addMatrix; 134 apply->refresh(*fMaker); 135 apply->activate(*fMaker); 136 apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000)); 137 matrix = (SkDrawMatrix*) apply->getScope(); 138 } 139 } 140 SkScalar result = 0; 141 SkAnimatorScript::EvaluateFloat(*fMaker, NULL, fDraw->spacing.c_str(), &result); 142 if (drawPath) 143 dst->addPath(drawPath->getPath(), m); 144 fMaker->clearExtraPropertyCallBack(fDraw->fType); 145 return result; 146 } 147 148private: 149 virtual void flatten(SkFlattenableWriteBuffer& ) {} 150 virtual Factory getFactory() { return NULL; } 151 152 static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) { 153 if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) { 154 value->fOperand.fScalar = *(SkScalar*) clen; 155 value->fType = SkType_Float; 156 return true; 157 } 158 return false; 159 } 160 161 static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) { 162 if (SK_LITERAL_STR_EQUAL("distance", token, len)) { 163 value->fOperand.fScalar = *(SkScalar*) dist; 164 value->fType = SkType_Float; 165 return true; 166 } 167 return false; 168 } 169 170 SkDrawShape1DPathEffect* fDraw; 171 SkAnimateMaker* fMaker; 172}; 173 174//////////// SkDrawShapePathEffect 175 176#if SK_USE_CONDENSED_INFO == 0 177 178const SkMemberInfo SkDrawShapePathEffect::fInfo[] = { 179 SK_MEMBER(addMatrix, Drawable), // either matrix or apply 180 SK_MEMBER(addPath, Drawable), // either path or apply 181 SK_MEMBER(path, Path), 182}; 183 184#endif 185 186DEFINE_GET_MEMBER(SkDrawShapePathEffect); 187 188SkDrawShapePathEffect::SkDrawShapePathEffect() : 189 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) { 190} 191 192SkDrawShapePathEffect::~SkDrawShapePathEffect() { 193 fPathEffect->safeUnref(); 194} 195 196bool SkDrawShapePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { 197 path = (SkDrawPath*) child; 198 return true; 199} 200 201SkPathEffect* SkDrawShapePathEffect::getPathEffect() { 202 fPathEffect->ref(); 203 return fPathEffect; 204} 205 206//////////// SkDrawShape1DPathEffect 207 208#if SK_USE_CONDENSED_INFO == 0 209 210const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = { 211 SK_MEMBER_INHERITED, 212 SK_MEMBER(phase, String), 213 SK_MEMBER(spacing, String), 214}; 215 216#endif 217 218DEFINE_GET_MEMBER(SkDrawShape1DPathEffect); 219 220SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) { 221} 222 223SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() { 224} 225 226void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) { 227 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false)) 228 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error 229 else 230 fPathEffect = new SkShape1DPathEffect(this, &maker); 231} 232 233////////// SkShape2DPathEffect 234 235class SkShape2DPathEffect : public Sk2DPathEffect { 236public: 237 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker, 238 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) { 239 } 240 241protected: 242 virtual void begin(const SkIRect& uvBounds, SkPath* ) 243 { 244 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop), 245 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom)); 246 } 247 248 virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) 249 { 250 fLoc = loc; 251 fU = u; 252 fV = v; 253 SkDrawPath* drawPath; 254 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this); 255 if (fDraw->addPath->isPath()) { 256 drawPath = (SkDrawPath*) fDraw->addPath; 257 } else { 258 SkApply* apply = (SkApply*) fDraw->addPath; 259 apply->refresh(*fMaker); 260 apply->activate(*fMaker); 261 apply->interpolate(*fMaker, v); 262 drawPath = (SkDrawPath*) apply->getScope(); 263 } 264 if (drawPath == NULL) 265 goto clearCallBack; 266 if (fDraw->matrix) { 267 SkDrawMatrix* matrix; 268 if (fDraw->matrix->getType() == SkType_Matrix) 269 matrix = (SkDrawMatrix*) fDraw->matrix; 270 else { 271 SkApply* apply = (SkApply*) fDraw->matrix; 272 apply->activate(*fMaker); 273 apply->interpolate(*fMaker, v); 274 matrix = (SkDrawMatrix*) apply->getScope(); 275 } 276 if (matrix) { 277 dst->addPath(drawPath->getPath(), matrix->getMatrix()); 278 goto clearCallBack; 279 } 280 } 281 dst->addPath(drawPath->getPath()); 282clearCallBack: 283 fMaker->clearExtraPropertyCallBack(fDraw->fType); 284 } 285 286private: 287 288 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) { 289 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ; 290 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D; 291 int index; 292 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false) 293 return false; 294 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6); 295 if (index < 6) { 296 value->fType = SkType_Float; 297 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index]; 298 } else { 299 value->fType = SkType_Int; 300 value->fOperand.fS32 = (&shape2D->fU)[index - 6]; 301 } 302 return true; 303 } 304 305 SkPoint fLoc; 306 SkRect fUVBounds; 307 int32_t fU; 308 int32_t fV; 309 SkDrawShape2DPathEffect* fDraw; 310 SkAnimateMaker* fMaker; 311 312 // illegal 313 SkShape2DPathEffect(const SkShape2DPathEffect&); 314 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&); 315}; 316 317////////// SkDrawShape2DPathEffect 318 319#if SK_USE_CONDENSED_INFO == 0 320 321const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = { 322 SK_MEMBER_INHERITED, 323 SK_MEMBER(matrix, Matrix) 324}; 325 326#endif 327 328DEFINE_GET_MEMBER(SkDrawShape2DPathEffect); 329 330SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) { 331} 332 333SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() { 334} 335 336void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) { 337 if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false) || 338 matrix == NULL) 339 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error 340 else 341 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix()); 342} 343 344////////// SkDrawComposePathEffect 345 346#if SK_USE_CONDENSED_INFO == 0 347 348const SkMemberInfo SkDrawComposePathEffect::fInfo[] = { 349 SK_MEMBER(effect1, PathEffect), 350 SK_MEMBER(effect2, PathEffect) 351}; 352 353#endif 354 355DEFINE_GET_MEMBER(SkDrawComposePathEffect); 356 357SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type), 358 effect1(NULL), effect2(NULL) { 359} 360 361SkDrawComposePathEffect::~SkDrawComposePathEffect() { 362 delete effect1; 363 delete effect2; 364} 365 366bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { 367 if (effect1 == NULL) 368 effect1 = (SkDrawPathEffect*) child; 369 else 370 effect2 = (SkDrawPathEffect*) child; 371 return true; 372} 373 374SkPathEffect* SkDrawComposePathEffect::getPathEffect() { 375 SkPathEffect* e1 = effect1->getPathEffect(); 376 SkPathEffect* e2 = effect2->getPathEffect(); 377 SkPathEffect* composite = new SkComposePathEffect(e1, e2); 378 e1->unref(); 379 e2->unref(); 380 return composite; 381} 382 383bool SkDrawComposePathEffect::isPaint() const { 384 return true; 385} 386 387//////////// SkDrawCornerPathEffect 388 389#if SK_USE_CONDENSED_INFO == 0 390 391const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = { 392 SK_MEMBER(radius, Float) 393}; 394 395#endif 396 397DEFINE_GET_MEMBER(SkDrawCornerPathEffect); 398 399SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type): 400 fType(type), radius(0) { 401} 402 403SkDrawCornerPathEffect::~SkDrawCornerPathEffect() { 404} 405 406SkPathEffect* SkDrawCornerPathEffect::getPathEffect() { 407 return new SkCornerPathEffect(radius); 408} 409 410///////// 411 412#include "SkExtras.h" 413 414const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D"; 415const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D"; 416const char kDrawComposePathEffectName[] = "pathEffect:compose"; 417const char kDrawCornerPathEffectName[] = "pathEffect:corner"; 418 419class SkExtraPathEffects : public SkExtras { 420public: 421 SkExtraPathEffects(SkAnimator* animator) : 422 skDrawShape1DPathEffectType(SkType_Unknown), 423 skDrawShape2DPathEffectType(SkType_Unknown), 424 skDrawComposePathEffectType(SkType_Unknown), 425 skDrawCornerPathEffectType(SkType_Unknown) { 426 } 427 428 virtual SkDisplayable* createInstance(SkDisplayTypes type) { 429 SkDisplayable* result = NULL; 430 if (skDrawShape1DPathEffectType == type) 431 result = new SkDrawShape1DPathEffect(type); 432 else if (skDrawShape2DPathEffectType == type) 433 result = new SkDrawShape2DPathEffect(type); 434 else if (skDrawComposePathEffectType == type) 435 result = new SkDrawComposePathEffect(type); 436 else if (skDrawCornerPathEffectType == type) 437 result = new SkDrawCornerPathEffect(type); 438 return result; 439 } 440 441 virtual bool definesType(SkDisplayTypes type) { 442 return type == skDrawShape1DPathEffectType || 443 type == skDrawShape2DPathEffectType || 444 type == skDrawComposePathEffectType || 445 type == skDrawCornerPathEffectType; 446 } 447 448#if SK_USE_CONDENSED_INFO == 0 449 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) { 450 const SkMemberInfo* info = NULL; 451 int infoCount = 0; 452 if (skDrawShape1DPathEffectType == type) { 453 info = SkDrawShape1DPathEffect::fInfo; 454 infoCount = SkDrawShape1DPathEffect::fInfoCount; 455 } else if (skDrawShape2DPathEffectType == type) { 456 info = SkDrawShape2DPathEffect::fInfo; 457 infoCount = SkDrawShape2DPathEffect::fInfoCount; 458 } else if (skDrawComposePathEffectType == type) { 459 info = SkDrawComposePathEffect::fInfo; 460 infoCount = SkDrawShape1DPathEffect::fInfoCount; 461 } else if (skDrawCornerPathEffectType == type) { 462 info = SkDrawCornerPathEffect::fInfo; 463 infoCount = SkDrawCornerPathEffect::fInfoCount; 464 } 465 if (infoCountPtr) 466 *infoCountPtr = infoCount; 467 return info; 468 } 469#endif 470 471#ifdef SK_DEBUG 472 virtual const char* getName(SkDisplayTypes type) { 473 if (skDrawShape1DPathEffectType == type) 474 return kDrawShape1DPathEffectName; 475 else if (skDrawShape2DPathEffectType == type) 476 return kDrawShape2DPathEffectName; 477 else if (skDrawComposePathEffectType == type) 478 return kDrawComposePathEffectName; 479 else if (skDrawCornerPathEffectType == type) 480 return kDrawCornerPathEffectName; 481 return NULL; 482 } 483#endif 484 485 virtual SkDisplayTypes getType(const char name[], size_t len ) { 486 SkDisplayTypes* type = NULL; 487 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len)) 488 type = &skDrawShape1DPathEffectType; 489 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len)) 490 type = &skDrawShape2DPathEffectType; 491 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len)) 492 type = &skDrawComposePathEffectType; 493 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len)) 494 type = &skDrawCornerPathEffectType; 495 if (type) { 496 if (*type == SkType_Unknown) 497 *type = SkDisplayType::RegisterNewType(); 498 return *type; 499 } 500 return SkType_Unknown; 501 } 502 503private: 504 SkDisplayTypes skDrawShape1DPathEffectType; 505 SkDisplayTypes skDrawShape2DPathEffectType; 506 SkDisplayTypes skDrawComposePathEffectType; 507 SkDisplayTypes skDrawCornerPathEffectType; 508}; 509 510 511void InitializeSkExtraPathEffects(SkAnimator* animator) { 512 animator->addExtras(new SkExtraPathEffects(animator)); 513} 514 515//////////////// 516 517 518SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) { 519} 520