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 |