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