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