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