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