Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrRRectEffect.h" | 8 #include "GrRRectEffect.h" |
| 9 | 9 |
| 10 #include "gl/GrGLEffect.h" | 10 #include "gl/GrGLEffect.h" |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 fPrevRRect = rrect; | 370 fPrevRRect = rrect; |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 | 373 |
| 374 ////////////////////////////////////////////////////////////////////////////// | 374 ////////////////////////////////////////////////////////////////////////////// |
| 375 | 375 |
| 376 class GLEllipticalRRectEffect; | 376 class GLEllipticalRRectEffect; |
| 377 | 377 |
| 378 class EllipticalRRectEffect : public GrEffect { | 378 class EllipticalRRectEffect : public GrEffect { |
| 379 public: | 379 public: |
| 380 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. | 380 enum RRectType { |
| 381 kSimple_RRectType, | |
| 382 kNinePatch_RRectType, | |
|
jvanverth1
2014/03/12 13:37:55
This might be worth adding to SkRRect.
bsalomon
2014/03/12 14:34:55
Will do in follow-up CL
| |
| 383 }; | |
| 384 | |
| 385 // This effect only supports rrects where the radii are >= kRadiusMin. | |
| 381 static const SkScalar kRadiusMin; | 386 static const SkScalar kRadiusMin; |
| 382 | 387 |
| 383 static GrEffectRef* Create(GrEffectEdgeType, const SkRRect&); | 388 static GrEffectRef* Create(GrEffectEdgeType, RRectType, const SkRRect&); |
| 384 | 389 |
| 385 virtual ~EllipticalRRectEffect() {}; | 390 virtual ~EllipticalRRectEffect() {}; |
| 386 static const char* Name() { return "EllipticalRRect"; } | 391 static const char* Name() { return "EllipticalRRect"; } |
| 387 | 392 |
| 388 const SkRRect& getRRect() const { return fRRect; } | 393 const SkRRect& getRRect() const { return fRRect; } |
| 389 | 394 |
| 395 RRectType getRRectType() const { return fRRectType; } | |
| 396 | |
| 390 GrEffectEdgeType getEdgeType() const { return fEdgeType; } | 397 GrEffectEdgeType getEdgeType() const { return fEdgeType; } |
| 391 | 398 |
| 392 typedef GLEllipticalRRectEffect GLEffect; | 399 typedef GLEllipticalRRectEffect GLEffect; |
| 393 | 400 |
| 394 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; | 401 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; |
| 395 | 402 |
| 396 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 403 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 397 | 404 |
| 398 private: | 405 private: |
| 399 EllipticalRRectEffect(GrEffectEdgeType, const SkRRect&); | 406 EllipticalRRectEffect(GrEffectEdgeType, RRectType, const SkRRect&); |
| 400 | 407 |
| 401 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 408 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 402 | 409 |
| 403 SkRRect fRRect; | 410 SkRRect fRRect; |
| 411 RRectType fRRectType; | |
| 404 GrEffectEdgeType fEdgeType; | 412 GrEffectEdgeType fEdgeType; |
| 405 | 413 |
| 406 GR_DECLARE_EFFECT_TEST; | 414 GR_DECLARE_EFFECT_TEST; |
| 407 | 415 |
| 408 typedef GrEffect INHERITED; | 416 typedef GrEffect INHERITED; |
| 409 }; | 417 }; |
| 410 | 418 |
| 411 const SkScalar EllipticalRRectEffect::kRadiusMin = 0.5f; | 419 const SkScalar EllipticalRRectEffect::kRadiusMin = 0.5f; |
| 412 | 420 |
| 413 GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType, | 421 GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType, |
| 422 RRectType rrType, | |
| 414 const SkRRect& rrect) { | 423 const SkRRect& rrect) { |
| 415 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); | 424 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge Type == edgeType); |
| 416 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (ed geType, rrect)))); | 425 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (ed geType, rrType, |
| 426 rr ect)))); | |
| 417 } | 427 } |
| 418 | 428 |
| 419 void EllipticalRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { | 429 void EllipticalRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { |
| 420 *validFlags = 0; | 430 *validFlags = 0; |
| 421 } | 431 } |
| 422 | 432 |
| 423 const GrBackendEffectFactory& EllipticalRRectEffect::getFactory() const { | 433 const GrBackendEffectFactory& EllipticalRRectEffect::getFactory() const { |
| 424 return GrTBackendEffectFactory<EllipticalRRectEffect>::getInstance(); | 434 return GrTBackendEffectFactory<EllipticalRRectEffect>::getInstance(); |
| 425 } | 435 } |
| 426 | 436 |
| 427 EllipticalRRectEffect::EllipticalRRectEffect(GrEffectEdgeType edgeType, const Sk RRect& rrect) | 437 EllipticalRRectEffect::EllipticalRRectEffect(GrEffectEdgeType edgeType, RRectTyp e rrType, |
| 438 const SkRRect& rrect) | |
| 428 : fRRect(rrect) | 439 : fRRect(rrect) |
| 440 , fRRectType(rrType) | |
| 429 , fEdgeType(edgeType){ | 441 , fEdgeType(edgeType){ |
| 430 this->setWillReadFragmentPosition(); | 442 this->setWillReadFragmentPosition(); |
| 431 } | 443 } |
| 432 | 444 |
| 433 bool EllipticalRRectEffect::onIsEqual(const GrEffect& other) const { | 445 bool EllipticalRRectEffect::onIsEqual(const GrEffect& other) const { |
| 434 const EllipticalRRectEffect& erre = CastEffect<EllipticalRRectEffect>(other) ; | 446 const EllipticalRRectEffect& erre = CastEffect<EllipticalRRectEffect>(other) ; |
| 447 // No need to check fRRectType as it is derived from fRRect. | |
| 435 return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect; | 448 return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect; |
| 436 } | 449 } |
| 437 | 450 |
| 438 ////////////////////////////////////////////////////////////////////////////// | 451 ////////////////////////////////////////////////////////////////////////////// |
| 439 | 452 |
| 440 GR_DEFINE_EFFECT_TEST(EllipticalRRectEffect); | 453 GR_DEFINE_EFFECT_TEST(EllipticalRRectEffect); |
| 441 | 454 |
| 442 GrEffectRef* EllipticalRRectEffect::TestCreate(SkRandom* random, | 455 GrEffectRef* EllipticalRRectEffect::TestCreate(SkRandom* random, |
| 443 GrContext*, | 456 GrContext*, |
| 444 const GrDrawTargetCaps& caps, | 457 const GrDrawTargetCaps& caps, |
| 445 GrTexture*[]) { | 458 GrTexture*[]) { |
| 446 SkScalar w = random->nextRangeScalar(20.f, 1000.f); | 459 SkScalar w = random->nextRangeScalar(20.f, 1000.f); |
| 447 SkScalar h = random->nextRangeScalar(20.f, 1000.f); | 460 SkScalar h = random->nextRangeScalar(20.f, 1000.f); |
| 448 SkScalar rx = random->nextRangeF(kRadiusMin, 9.f); | 461 SkVector r[4]; |
| 449 SkScalar ry = random->nextRangeF(kRadiusMin, 9.f); | 462 r[SkRRect::kUpperLeft_Corner].fX = random->nextRangeF(kRadiusMin, 9.f); |
| 463 // ensure at least one corner really is elliptical | |
| 464 do { | |
| 465 r[SkRRect::kUpperLeft_Corner].fY = random->nextRangeF(kRadiusMin, 9.f); | |
| 466 } while (r[SkRRect::kUpperLeft_Corner].fY == r[SkRRect::kUpperLeft_Corner].f X); | |
| 467 | |
| 450 SkRRect rrect; | 468 SkRRect rrect; |
| 451 rrect.setRectXY(SkRect::MakeWH(w, h), rx, ry); | 469 if (random->nextBool()) { |
| 470 // half the time create a four-radii rrect. | |
| 471 r[SkRRect::kLowerRight_Corner].fX = random->nextRangeF(kRadiusMin, 9.f); | |
| 472 r[SkRRect::kLowerRight_Corner].fY = random->nextRangeF(kRadiusMin, 9.f); | |
| 473 | |
| 474 r[SkRRect::kUpperRight_Corner].fX = r[SkRRect::kLowerRight_Corner].fX; | |
| 475 r[SkRRect::kUpperRight_Corner].fY = r[SkRRect::kUpperLeft_Corner].fY; | |
| 476 | |
| 477 r[SkRRect::kLowerLeft_Corner].fX = r[SkRRect::kUpperLeft_Corner].fX; | |
| 478 r[SkRRect::kLowerLeft_Corner].fY = r[SkRRect::kLowerRight_Corner].fY; | |
| 479 | |
| 480 rrect.setRectRadii(SkRect::MakeWH(w, h), r); | |
| 481 } else { | |
| 482 rrect.setRectXY(SkRect::MakeWH(w, h), r[SkRRect::kUpperLeft_Corner].fX, | |
| 483 r[SkRRect::kUpperLeft_Corner].fY); | |
| 484 } | |
| 452 GrEffectRef* effect; | 485 GrEffectRef* effect; |
| 453 do { | 486 do { |
| 454 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); | 487 GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectE dgeTypeCnt); |
| 455 effect = EllipticalRRectEffect::Create(et, rrect); | 488 effect = GrRRectEffect::Create(et, rrect); |
| 456 } while (NULL == effect); | 489 } while (NULL == effect); |
| 457 return effect; | 490 return effect; |
| 458 } | 491 } |
| 459 | 492 |
| 460 ////////////////////////////////////////////////////////////////////////////// | 493 ////////////////////////////////////////////////////////////////////////////// |
| 461 | 494 |
| 462 class GLEllipticalRRectEffect : public GrGLEffect { | 495 class GLEllipticalRRectEffect : public GrGLEffect { |
| 463 public: | 496 public: |
| 464 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 497 GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| 465 | 498 |
| 466 virtual void emitCode(GrGLShaderBuilder* builder, | 499 virtual void emitCode(GrGLShaderBuilder* builder, |
| 467 const GrDrawEffect& drawEffect, | 500 const GrDrawEffect& drawEffect, |
| 468 EffectKey key, | 501 EffectKey key, |
| 469 const char* outputColor, | 502 const char* outputColor, |
| 470 const char* inputColor, | 503 const char* inputColor, |
| 471 const TransformedCoordsArray&, | 504 const TransformedCoordsArray&, |
| 472 const TextureSamplerArray&) SK_OVERRIDE; | 505 const TextureSamplerArray&) SK_OVERRIDE; |
| 473 | 506 |
| 474 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); | 507 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
| 475 | 508 |
| 476 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | 509 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; |
| 477 | 510 |
| 478 private: | 511 private: |
| 479 GrGLUniformManager::UniformHandle fInnerRectUniform; | 512 GrGLUniformManager::UniformHandle fInnerRectUniform; |
| 480 GrGLUniformManager::UniformHandle fInvRadiusXYSqdUniform; | 513 GrGLUniformManager::UniformHandle fInvRadiiSqdUniform; |
| 481 SkRRect fPrevRRect; | 514 SkRRect fPrevRRect; |
| 482 typedef GrGLEffect INHERITED; | 515 typedef GrGLEffect INHERITED; |
| 483 }; | 516 }; |
| 484 | 517 |
| 485 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f actory, | 518 GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& f actory, |
| 486 const GrDrawEffect& drawEffect) | 519 const GrDrawEffect& drawEffect) |
| 487 : INHERITED (factory) { | 520 : INHERITED (factory) { |
| 488 fPrevRRect.setEmpty(); | 521 fPrevRRect.setEmpty(); |
| 489 } | 522 } |
| 490 | 523 |
| 491 void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, | 524 void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder, |
| 492 const GrDrawEffect& drawEffect, | 525 const GrDrawEffect& drawEffect, |
| 493 EffectKey key, | 526 EffectKey key, |
| 494 const char* outputColor, | 527 const char* outputColor, |
| 495 const char* inputColor, | 528 const char* inputColor, |
| 496 const TransformedCoordsArray&, | 529 const TransformedCoordsArray&, |
| 497 const TextureSamplerArray& samplers) { | 530 const TextureSamplerArray& samplers) { |
| 498 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | 531 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); |
| 499 const char *rectName; | 532 const char *rectName; |
| 500 const char *invRadiusXYSqdName; | |
| 501 // The inner rect is the rrect bounds inset by the x/y radii | 533 // The inner rect is the rrect bounds inset by the x/y radii |
| 502 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, | 534 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, |
| 503 kVec4f_GrSLType, | 535 kVec4f_GrSLType, |
| 504 "innerRect", | 536 "innerRect", |
| 505 &rectName); | 537 &rectName); |
| 506 fInvRadiusXYSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi sibility, | |
| 507 kVec2f_GrSLType, | |
| 508 "invRadiusXY", | |
| 509 &invRadiusXYSqdName); | |
| 510 const char* fragmentPos = builder->fragmentPosition(); | 538 const char* fragmentPos = builder->fragmentPosition(); |
| 511 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos | 539 // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos |
| 512 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant | 540 // to the ellipse center. The vector is pinned in x and y to be in the quart er-plane relevant |
| 513 // to that corner. This means that points near the interior near the rrect t op edge will have | 541 // to that corner. This means that points near the interior near the rrect t op edge will have |
| 514 // a vector that points straight up for both the TL left and TR corners. Com puting an | 542 // a vector that points straight up for both the TL left and TR corners. Com puting an |
| 515 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, | 543 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, |
| 516 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | 544 // fragments near the other three edges will get the correct AA. Fragments i n the interior of |
| 517 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will | 545 // the rrect will have a (0,0) vector at all four corners. So long as the ra dii > 0.5 they will |
| 518 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | 546 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. |
| 519 // The code below is a simplified version of the above that performs maxs on the vector | 547 // The code below is a simplified version of the above that performs maxs on the vector |
| 520 // components before computing distances and alpha values so that only one d istance computation | 548 // components before computing distances and alpha values so that only one d istance computation |
| 521 // need be computed to determine the min alpha. | 549 // need be computed to determine the min alpha. |
| 522 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); | 550 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); |
| 523 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); | 551 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); |
| 524 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); | 552 switch (erre.getRRectType()) { |
| 525 // Z is the x/y offsets divided by squared radii. | 553 case EllipticalRRectEffect::kSimple_RRectType: { |
| 526 builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiusXYSqdName); | 554 const char *invRadiiXYSqdName; |
| 555 fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragme nt_Visibility, | |
| 556 kVec2f_GrSLType, | |
| 557 "invRadiiXY", | |
| 558 &invRadiiXYSqdName); | |
| 559 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; | |
| 560 // Z is the x/y offsets divided by squared radii. | |
| 561 builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName ); | |
| 562 break; | |
| 563 } | |
| 564 case EllipticalRRectEffect::kNinePatch_RRectType: { | |
| 565 const char *invRadiiLTRBSqdName; | |
| 566 fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragme nt_Visibility, | |
| 567 kVec4f_GrSLType, | |
| 568 "invRadiiLTRB", | |
| 569 &invRadiiLTRBSqdName); | |
| 570 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n") ; | |
| 571 // Z is the x/y offsets divided by squared radii. We only care about the (at most) one | |
| 572 // corner where both the x and y offsets are positive, hence the max es. (The inverse | |
| 573 // squared radii will always be positive.) | |
| 574 builder->fsCodeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s .zw), 0.0);\n", | |
| 575 invRadiiLTRBSqdName, invRadiiLTRBSqdName); | |
| 576 break; | |
| 577 } | |
| 578 } | |
| 527 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. | 579 // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1. |
| 528 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); | 580 builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n"); |
| 529 // grad_dot is the squared length of the gradient of the implicit. | 581 // grad_dot is the squared length of the gradient of the implicit. |
| 530 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n", fragmentPo s); | 582 builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n", fragmentPo s); |
| 531 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); | 583 builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n"); |
| 532 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n", | 584 builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_ dot);\n", |
| 533 fragmentPos); | 585 fragmentPos); |
| 534 | 586 |
| 535 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { | 587 if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) { |
| 536 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n"); | 588 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1 .0);\n"); |
| 537 } else { | 589 } else { |
| 538 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n"); | 590 builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1 .0);\n"); |
| 539 } | 591 } |
| 540 | 592 |
| 541 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 593 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 542 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); | 594 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); |
| 543 } | 595 } |
| 544 | 596 |
| 545 GrGLEffect::EffectKey GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEf fect, | 597 GrGLEffect::EffectKey GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEf fect, |
| 546 const GrGLCaps&) { | 598 const GrGLCaps&) { |
| 547 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | 599 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); |
| 548 return erre.getEdgeType(); | 600 GR_STATIC_ASSERT(kLast_GrEffectEdgeType < (1 << 3)); |
| 601 return erre.getRRectType() | erre.getEdgeType() << 3; | |
| 549 } | 602 } |
| 550 | 603 |
| 551 void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman, | 604 void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman, |
| 552 const GrDrawEffect& drawEffect) { | 605 const GrDrawEffect& drawEffect) { |
| 553 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); | 606 const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEff ect>(); |
| 554 const SkRRect& rrect = erre.getRRect(); | 607 const SkRRect& rrect = erre.getRRect(); |
| 555 if (rrect != fPrevRRect) { | 608 if (rrect != fPrevRRect) { |
| 556 SkRect rect = rrect.getBounds(); | 609 SkRect rect = rrect.getBounds(); |
| 557 SkASSERT(rrect.isSimple()); | 610 const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner); |
| 558 const SkVector& radius = rrect.getSimpleRadii(); | 611 SkASSERT(r0.fX >= EllipticalRRectEffect::kRadiusMin); |
| 559 SkASSERT(radius.fX >= EllipticalRRectEffect::kRadiusMin); | 612 SkASSERT(r0.fY >= EllipticalRRectEffect::kRadiusMin); |
| 560 SkASSERT(radius.fY >= EllipticalRRectEffect::kRadiusMin); | 613 switch (erre.getRRectType()) { |
| 561 rect.inset(radius.fX, radius.fY); | 614 case EllipticalRRectEffect::kSimple_RRectType: |
| 615 rect.inset(r0.fX, r0.fY); | |
| 616 uman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), | |
|
jvanverth1
2014/03/12 13:37:55
Use SkScalarInvert or SkScalarFastInvert?
bsalomon
2014/03/12 14:34:55
I checked with Mike and he sez using SkScalarInver
| |
| 617 1.f / (r0.fY * r0.fY)); | |
| 618 break; | |
| 619 case EllipticalRRectEffect::kNinePatch_RRectType: { | |
| 620 const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner); | |
| 621 SkASSERT(r1.fX >= EllipticalRRectEffect::kRadiusMin); | |
| 622 SkASSERT(r1.fY >= EllipticalRRectEffect::kRadiusMin); | |
| 623 rect.fLeft += r0.fX; | |
| 624 rect.fTop += r0.fY; | |
| 625 rect.fRight -= r1.fX; | |
| 626 rect.fBottom -= r1.fY; | |
| 627 uman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX), | |
| 628 1.f / (r0.fY * r0.fY), | |
| 629 1.f / (r1.fX * r1.fX), | |
| 630 1.f / (r1.fY * r1.fY)); | |
| 631 break; | |
| 632 } | |
| 633 } | |
| 562 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); | 634 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); |
| 563 uman.set2f(fInvRadiusXYSqdUniform, 1.f / (radius.fX * radius.fX), | |
| 564 1.f / (radius.fY * radius.fY)); | |
| 565 fPrevRRect = rrect; | 635 fPrevRRect = rrect; |
| 566 } | 636 } |
| 567 } | 637 } |
| 568 | 638 |
| 569 ////////////////////////////////////////////////////////////////////////////// | 639 ////////////////////////////////////////////////////////////////////////////// |
| 570 | 640 |
| 571 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) { | 641 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre ct) { |
| 572 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) { | 642 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) { |
| 573 return NULL; | 643 return NULL; |
| 574 } | 644 } |
| 575 uint32_t cornerFlags; | 645 uint32_t cornerFlags; |
| 576 if (rrect.isSimple()) { | 646 if (rrect.isSimple()) { |
| 577 if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) { | 647 if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) { |
| 578 if (rrect.getSimpleRadii().fX < CircularRRectEffect::kRadiusMin) { | 648 if (rrect.getSimpleRadii().fX < CircularRRectEffect::kRadiusMin) { |
| 579 return NULL; | 649 return NULL; |
| 580 } | 650 } |
| 581 cornerFlags = CircularRRectEffect::kAll_CornerFlags; | 651 cornerFlags = CircularRRectEffect::kAll_CornerFlags; |
| 582 } else { | 652 } else { |
| 583 if (rrect.getSimpleRadii().fX < EllipticalRRectEffect::kRadiusMin || | 653 if (rrect.getSimpleRadii().fX < EllipticalRRectEffect::kRadiusMin || |
| 584 rrect.getSimpleRadii().fY < EllipticalRRectEffect::kRadiusMin) { | 654 rrect.getSimpleRadii().fY < EllipticalRRectEffect::kRadiusMin) { |
| 585 return NULL; | 655 return NULL; |
| 586 } | 656 } |
| 587 return EllipticalRRectEffect::Create(edgeType, rrect); | 657 return EllipticalRRectEffect::Create(edgeType, |
| 658 EllipticalRRectEffect::kSimple_ RRectType, rrect); | |
| 588 } | 659 } |
| 589 } else if (rrect.isComplex()) { | 660 } else if (rrect.isComplex()) { |
| 590 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. | 661 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. |
| 591 SkScalar radius = 0; | 662 SkScalar radius = 0; |
| 592 cornerFlags = 0; | 663 cornerFlags = 0; |
| 593 for (int c = 0; c < 4; ++c) { | 664 for (int c = 0; c < 4; ++c) { |
| 594 const SkVector& r = rrect.radii((SkRRect::Corner)c); | 665 const SkVector& r = rrect.radii((SkRRect::Corner)c); |
| 595 SkASSERT((0 == r.fX) == (0 == r.fY)); | 666 SkASSERT((0 == r.fX) == (0 == r.fY)); |
| 596 if (0 == r.fX) { | 667 if (0 == r.fX) { |
| 597 continue; | 668 continue; |
| 598 } | 669 } |
| 599 if (r.fX != r.fY) { | 670 if (r.fX != r.fY) { |
| 600 return NULL; | 671 cornerFlags = -1; |
|
jvanverth1
2014/03/12 13:37:55
This seems a little hacky, but I don't have a bett
bsalomon
2014/03/12 14:34:55
yup :)
| |
| 672 break; | |
| 601 } | 673 } |
| 602 if (!cornerFlags) { | 674 if (!cornerFlags) { |
| 603 radius = r.fX; | 675 radius = r.fX; |
| 604 if (radius < CircularRRectEffect::kRadiusMin) { | 676 if (radius < CircularRRectEffect::kRadiusMin) { |
| 605 return NULL; | 677 cornerFlags = -1; |
| 678 break; | |
| 606 } | 679 } |
| 607 cornerFlags = 1 << c; | 680 cornerFlags = 1 << c; |
| 608 } else { | 681 } else { |
| 609 if (r.fX != radius) { | 682 if (r.fX != radius) { |
| 610 return NULL; | 683 cornerFlags = -1; |
| 684 break; | |
| 611 } | 685 } |
| 612 cornerFlags |= 1 << c; | 686 cornerFlags |= 1 << c; |
| 613 } | 687 } |
| 614 } | 688 } |
| 615 | 689 |
| 616 switch (cornerFlags) { | 690 switch (cornerFlags) { |
| 617 case CircularRRectEffect::kTopLeft_CornerFlag: | 691 case CircularRRectEffect::kTopLeft_CornerFlag: |
| 618 case CircularRRectEffect::kTopRight_CornerFlag: | 692 case CircularRRectEffect::kTopRight_CornerFlag: |
| 619 case CircularRRectEffect::kBottomRight_CornerFlag: | 693 case CircularRRectEffect::kBottomRight_CornerFlag: |
| 620 case CircularRRectEffect::kBottomLeft_CornerFlag: | 694 case CircularRRectEffect::kBottomLeft_CornerFlag: |
| 621 case CircularRRectEffect::kLeft_CornerFlags: | 695 case CircularRRectEffect::kLeft_CornerFlags: |
| 622 case CircularRRectEffect::kTop_CornerFlags: | 696 case CircularRRectEffect::kTop_CornerFlags: |
| 623 case CircularRRectEffect::kRight_CornerFlags: | 697 case CircularRRectEffect::kRight_CornerFlags: |
| 624 case CircularRRectEffect::kBottom_CornerFlags: | 698 case CircularRRectEffect::kBottom_CornerFlags: |
| 625 case CircularRRectEffect::kAll_CornerFlags: | 699 case CircularRRectEffect::kAll_CornerFlags: |
| 626 break; | 700 break; |
| 627 default: | 701 default: |
| 702 if (rrect.isNinePatch()) { | |
| 703 const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner) ; | |
| 704 const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner ); | |
| 705 if (r0.fX >= EllipticalRRectEffect::kRadiusMin && | |
| 706 r0.fY >= EllipticalRRectEffect::kRadiusMin && | |
| 707 r1.fX >= EllipticalRRectEffect::kRadiusMin && | |
| 708 r1.fY >= EllipticalRRectEffect::kRadiusMin) { | |
| 709 return EllipticalRRectEffect::Create(edgeType, | |
| 710 EllipticalRRectEffect::k NinePatch_RRectType, | |
| 711 rrect); | |
| 712 } | |
| 713 } | |
| 628 return NULL; | 714 return NULL; |
| 629 } | 715 } |
| 630 } else { | 716 } else { |
| 631 return NULL; | 717 return NULL; |
| 632 } | 718 } |
| 633 return CircularRRectEffect::Create(edgeType, cornerFlags, rrect); | 719 return CircularRRectEffect::Create(edgeType, cornerFlags, rrect); |
| 634 } | 720 } |
| OLD | NEW |