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