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