text: /*
   * Copyright 2012 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #ifndef GrTextureDomainEffect_DEFINED
  #define GrTextureDomainEffect_DEFINED
  
  #include "GrSingleTextureEffect.h"
  #include "GrRect.h"
  
  class GrGLTextureDomainEffect;
  
  /**
   * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
   * the edge of the domain or result in a vec4 of zeros. The domain is clipped to normalized texture
   * coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the domain to affect the
   * read value unless the caller considers this when calculating the domain. TODO: This should be a
   * helper that can assist an effect rather than effect unto itself.
   */
  class GrTextureDomainEffect : public GrSingleTextureEffect {
  
  public:
      /**
       * If SkShader::kDecal_TileMode sticks then this enum could be replaced by SkShader::TileMode.
       * We could also consider replacing/augmenting Decal mode with Border mode where the color
       * outside of the domain is user-specifiable. Decal mode currently has a hard (non-lerped)
       * transition between the border and the interior.
       */
      enum WrapMode {
          kClamp_WrapMode,
          kDecal_WrapMode,
      };
  
      static GrEffectRef* Create(GrTexture*,
                                 const SkMatrix&,
                                 const SkRect& domain,
                                 WrapMode,
                                 bool bilerp = false);
  
      virtual ~GrTextureDomainEffect();
  
      static const char* Name() { return "TextureDomain"; }
  
      typedef GrGLTextureDomainEffect GLEffect;
  
      virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
      virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
  
      const SkRect& domain() const { return fTextureDomain; }
      WrapMode wrapMode() const { return fWrapMode; }
  
      /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
         texels neighboring the domain may be read. */
      static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
          SkScalar wInv = SK_Scalar1 / texture->width();
          SkScalar hInv = SK_Scalar1 / texture->height();
          SkRect result = {
              texelRect.fLeft * wInv,
              texelRect.fTop * hInv,
              texelRect.fRight * wInv,
              texelRect.fBottom * hInv
          };
          return result;
      }
  
  protected:
      WrapMode fWrapMode;
      SkRect   fTextureDomain;
  
  private:
      GrTextureDomainEffect(GrTexture*,
                            const SkMatrix&,
                            const GrRect& domain,
                            WrapMode,
                            bool bilerp);
  
      virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
  
      GR_DECLARE_EFFECT_TEST;
  
      typedef GrSingleTextureEffect INHERITED;
  };
  
  #endif
  