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