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 29 class SkDrawShapePathEffect : public SkDrawPathEffect { 30 DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect); 31 SkDrawShapePathEffect(); 32 virtual ~SkDrawShapePathEffect(); 33 virtual bool add(SkAnimateMaker& , SkDisplayable* ); 34 virtual SkPathEffect* getPathEffect(); 35 protected: 36 SkDrawable* addPath; 37 SkDrawable* addMatrix; 38 SkDrawPath* path; 39 SkPathEffect* fPathEffect; 40 friend class SkShape1DPathEffect; 41 friend class SkShape2DPathEffect; 42 }; 43 44 class SkDrawShape1DPathEffect : public SkDrawShapePathEffect { 45 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect); 46 SkDrawShape1DPathEffect(SkDisplayTypes ); 47 virtual ~SkDrawShape1DPathEffect(); 48 virtual void onEndElement(SkAnimateMaker& ); 49 private: 50 SkString phase; 51 SkString spacing; 52 friend class SkShape1DPathEffect; 53 typedef SkDrawShapePathEffect INHERITED; 54 }; 55 56 class SkDrawShape2DPathEffect : public SkDrawShapePathEffect { 57 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect); 58 SkDrawShape2DPathEffect(SkDisplayTypes ); 59 virtual ~SkDrawShape2DPathEffect(); 60 virtual void onEndElement(SkAnimateMaker& ); 61 private: 62 SkDrawMatrix* matrix; 63 friend class SkShape2DPathEffect; 64 typedef SkDrawShapePathEffect INHERITED; 65 }; 66 67 class 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; 74 private: 75 SkDrawPathEffect* effect1; 76 SkDrawPathEffect* effect2; 77 }; 78 79 class SkDrawCornerPathEffect : public SkDrawPathEffect { 80 DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect); 81 SkDrawCornerPathEffect(SkDisplayTypes ); 82 virtual ~SkDrawCornerPathEffect(); 83 virtual SkPathEffect* getPathEffect(); 84 private: 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 96 class SkShape1DPathEffect : public Sk1DPathEffect { 97 public: 98 SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) : 99 fDraw(draw), fMaker(maker) { 100 } 101 102 protected: 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 148 private: 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 178 const 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 186 DEFINE_GET_MEMBER(SkDrawShapePathEffect); 187 188 SkDrawShapePathEffect::SkDrawShapePathEffect() : 189 addPath(NULL), addMatrix(NULL), path(NULL), fPathEffect(NULL) { 190 } 191 192 SkDrawShapePathEffect::~SkDrawShapePathEffect() { 193 fPathEffect->safeUnref(); 194 } 195 196 bool SkDrawShapePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { 197 path = (SkDrawPath*) child; 198 return true; 199 } 200 201 SkPathEffect* SkDrawShapePathEffect::getPathEffect() { 202 fPathEffect->ref(); 203 return fPathEffect; 204 } 205 206 //////////// SkDrawShape1DPathEffect 207 208 #if SK_USE_CONDENSED_INFO == 0 209 210 const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = { 211 SK_MEMBER_INHERITED, 212 SK_MEMBER(phase, String), 213 SK_MEMBER(spacing, String), 214 }; 215 216 #endif 217 218 DEFINE_GET_MEMBER(SkDrawShape1DPathEffect); 219 220 SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) { 221 } 222 223 SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() { 224 } 225 226 void 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 235 class SkShape2DPathEffect : public Sk2DPathEffect { 236 public: 237 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker, 238 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) { 239 } 240 241 protected: 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()); 282 clearCallBack: 283 fMaker->clearExtraPropertyCallBack(fDraw->fType); 284 } 285 286 private: 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 321 const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = { 322 SK_MEMBER_INHERITED, 323 SK_MEMBER(matrix, Matrix) 324 }; 325 326 #endif 327 328 DEFINE_GET_MEMBER(SkDrawShape2DPathEffect); 329 330 SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) { 331 } 332 333 SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() { 334 } 335 336 void 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 348 const SkMemberInfo SkDrawComposePathEffect::fInfo[] = { 349 SK_MEMBER(effect1, PathEffect), 350 SK_MEMBER(effect2, PathEffect) 351 }; 352 353 #endif 354 355 DEFINE_GET_MEMBER(SkDrawComposePathEffect); 356 357 SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type), 358 effect1(NULL), effect2(NULL) { 359 } 360 361 SkDrawComposePathEffect::~SkDrawComposePathEffect() { 362 delete effect1; 363 delete effect2; 364 } 365 366 bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { 367 if (effect1 == NULL) 368 effect1 = (SkDrawPathEffect*) child; 369 else 370 effect2 = (SkDrawPathEffect*) child; 371 return true; 372 } 373 374 SkPathEffect* 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 383 bool SkDrawComposePathEffect::isPaint() const { 384 return true; 385 } 386 387 //////////// SkDrawCornerPathEffect 388 389 #if SK_USE_CONDENSED_INFO == 0 390 391 const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = { 392 SK_MEMBER(radius, Float) 393 }; 394 395 #endif 396 397 DEFINE_GET_MEMBER(SkDrawCornerPathEffect); 398 399 SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type): 400 fType(type), radius(0) { 401 } 402 403 SkDrawCornerPathEffect::~SkDrawCornerPathEffect() { 404 } 405 406 SkPathEffect* SkDrawCornerPathEffect::getPathEffect() { 407 return new SkCornerPathEffect(radius); 408 } 409 410 ///////// 411 412 #include "SkExtras.h" 413 414 const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D"; 415 const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D"; 416 const char kDrawComposePathEffectName[] = "pathEffect:compose"; 417 const char kDrawCornerPathEffectName[] = "pathEffect:corner"; 418 419 class SkExtraPathEffects : public SkExtras { 420 public: 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 503 private: 504 SkDisplayTypes skDrawShape1DPathEffectType; 505 SkDisplayTypes skDrawShape2DPathEffectType; 506 SkDisplayTypes skDrawComposePathEffectType; 507 SkDisplayTypes skDrawCornerPathEffectType; 508 }; 509 510 511 void InitializeSkExtraPathEffects(SkAnimator* animator) { 512 animator->addExtras(new SkExtraPathEffects(animator)); 513 } 514 515 //////////////// 516 517 518 SkExtras::SkExtras() : fExtraCallBack(NULL), fExtraStorage(NULL) { 519 } 520