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 |