Emulate distance field gamma fix by making glyphs thicker or thinner

The idea here is that we determine the 0.5 crossover for each
row in the gamma table, then invert the mapping to determine
which point that maps to in the original range [-.65,
.65]. That gives us a change in the apparent width of the
glyph that closely corresponds to the change produced by the gamma fix.

BUG=skia:2933

Review URL: https://codereview.chromium.org/1042373002
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 12aa1bf..90d6d76 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -43,6 +43,11 @@
 static const int kVerticesPerGlyph = 4;
 static const int kIndicesPerGlyph = 6;
 
+#ifdef SK_DEBUG
+static const int kExpectedDistanceAdjustTableSize = 8;
+#endif
+static const int kDistanceAdjustLumShift = 5;
+
 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
                                                        SkGpuDevice* gpuDevice,
                                                        const SkDeviceProperties& properties,
@@ -54,7 +59,7 @@
     fEnableDFRendering = enable;
 #endif
     fStrike = NULL;
-    fGammaTexture = NULL;
+    fDistanceAdjustTable = NULL;
 
     fEffectTextureUniqueID = SK_InvalidUniqueID;
     fEffectColor = GrColor_ILLEGAL;
@@ -75,6 +80,7 @@
                                                                bool enable) {
     GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextContext, 
                                                          (context, gpuDevice, props, enable));
+    textContext->buildDistanceAdjustTable();
 #ifdef USE_BITMAP_TEXTBLOBS
     textContext->fFallbackTextContext = GrBitmapTextContextB::Create(context, gpuDevice, props);
 #else
@@ -84,8 +90,92 @@
     return textContext;
 }
 
+void GrDistanceFieldTextContext::buildDistanceAdjustTable() {
+
+    // This is used for an approximation of the mask gamma hack, used by raster and bitmap
+    // text. The mask gamma hack is based off of guessing what the blend color is going to
+    // be, and adjusting the mask so that when run through the linear blend will
+    // produce the value closest to the desired result. However, in practice this means
+    // that the 'adjusted' mask is just increasing or decreasing the coverage of
+    // the mask depending on what it is thought it will blit against. For black (on
+    // assumed white) this means that coverages are decreased (on a curve). For white (on
+    // assumed black) this means that coverages are increased (on a a curve). At
+    // middle (perceptual) gray (which could be blit against anything) the coverages
+    // remain the same.
+    //
+    // The idea here is that instead of determining the initial (real) coverage and
+    // then adjusting that coverage, we determine an adjusted coverage directly by
+    // essentially manipulating the geometry (in this case, the distance to the glyph
+    // edge). So for black (on assumed white) this thins a bit; for white (on
+    // assumed black) this fake bolds the geometry a bit.
+    //
+    // The distance adjustment is calculated by determining the actual coverage value which
+    // when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This
+    // actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the
+    // actual edge. So by subtracting this distance adjustment and computing without the
+    // the coverage adjustment we should get 0.5 coverage at the same point.
+    //
+    // This has several implications:
+    //     For non-gray lcd smoothed text, each subpixel essentially is using a
+    //     slightly different geometry.
+    //
+    //     For black (on assumed white) this may not cover some pixels which were
+    //     previously covered; however those pixels would have been only slightly
+    //     covered and that slight coverage would have been decreased anyway. Also, some pixels
+    //     which were previously fully covered may no longer be fully covered.
+    //
+    //     For white (on assumed black) this may cover some pixels which weren't
+    //     previously covered at all.
+
+    int width, height;
+    size_t size;
+
+#ifdef SK_GAMMA_CONTRAST
+    SkScalar contrast = SK_GAMMA_CONTRAST;
+#else
+    SkScalar contrast = 0.5f;
+#endif
+    SkScalar paintGamma = fDeviceProperties.gamma();
+    SkScalar deviceGamma = fDeviceProperties.gamma();
+
+    size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
+        &width, &height);
+   
+    SkASSERT(kExpectedDistanceAdjustTableSize == height);
+    fDistanceAdjustTable = SkNEW_ARRAY(SkScalar, height);
+
+    SkAutoTArray<uint8_t> data((int)size);
+    SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get());
+
+    // find the inverse points where we cross 0.5
+    // binsearch might be better, but we only need to do this once on creation
+    for (int row = 0; row < height; ++row) {
+        uint8_t* rowPtr = data.get() + row*width;
+        for (int col = 0; col < width - 1; ++col) {
+            if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
+                // compute point where a mask value will give us a result of 0.5
+                float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]);
+                float borderAlpha = (col + interp) / 255.f;
+
+                // compute t value for that alpha
+                // this is an approximate inverse for smoothstep()
+                float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f;
+
+                // compute distance which gives us that t value
+                const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor
+                float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor;
+
+                fDistanceAdjustTable[row] = d;
+                break;
+            }
+        }
+    }
+}
+
+
 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
-    SkSafeSetNull(fGammaTexture);
+    SkDELETE_ARRAY(fDistanceAdjustTable);
+    fDistanceAdjustTable = NULL;
 }
 
 bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt,
@@ -183,45 +273,6 @@
     fSkPaint.setSubpixelText(true);
 }
 
-static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
-                                const SkDeviceProperties& deviceProperties,
-                                GrTexture** gammaTexture) {
-    if (NULL == *gammaTexture) {
-        int width, height;
-        size_t size;
-
-#ifdef SK_GAMMA_CONTRAST
-        SkScalar contrast = SK_GAMMA_CONTRAST;
-#else
-        SkScalar contrast = 0.5f;
-#endif
-        SkScalar paintGamma = deviceProperties.gamma();
-        SkScalar deviceGamma = deviceProperties.gamma();
-
-        size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
-                                                &width, &height);
-
-        SkAutoTArray<uint8_t> data((int)size);
-        SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get());
-
-        // TODO: Update this to use the cache rather than directly creating a texture.
-        GrSurfaceDesc desc;
-        desc.fFlags = kNone_GrSurfaceFlags;
-        desc.fWidth = width;
-        desc.fHeight = height;
-        desc.fConfig = kAlpha_8_GrPixelConfig;
-
-        *gammaTexture = context->getGpu()->createTexture(desc, true, NULL, 0);
-        if (NULL == *gammaTexture) {
-            return;
-        }
-
-        (*gammaTexture)->writePixels(0, 0, width, height,
-                                     (*gammaTexture)->config(), data.get(), 0,
-                                     GrContext::kDontFlush_PixelOpsFlag);
-    }
-}
-
 void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
                                             const GrPaint& paint,
                                             const SkPaint& skPaint, const SkMatrix& viewMatrix,
@@ -314,8 +365,6 @@
     SkGlyphCache*              cache = autoCache.getCache();
     GrFontScaler*              fontScaler = GetGrFontScaler(cache);
 
-    setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
-
     int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
     fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
 
@@ -443,13 +492,22 @@
         GrColor color = fPaint.getColor();
         if (fUseLCDText) {
             GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+
+            float redCorrection = 
+                fDistanceAdjustTable[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift];
+            float greenCorrection = 
+                fDistanceAdjustTable[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift];
+            float blueCorrection = 
+                fDistanceAdjustTable[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift];
+            GrDistanceFieldLCDTextureEffect::DistanceAdjust widthAdjust =
+                GrDistanceFieldLCDTextureEffect::DistanceAdjust::Make(redCorrection,
+                                                                   greenCorrection,
+                                                                   blueCorrection);
             fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(color,
                                                                                    fViewMatrix,
                                                                                    fCurrTexture,
                                                                                    params,
-                                                                                   fGammaTexture,
-                                                                                   gammaParams,
-                                                                                   colorNoPreMul,
+                                                                                   widthAdjust,
                                                                                    flags));
         } else {
             flags |= kColorAttr_DistanceFieldEffectFlag;
@@ -457,13 +515,12 @@
 #ifdef SK_GAMMA_APPLY_TO_A8
             U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(),
                                                                 filteredColor);
+            float correction = fDistanceAdjustTable[lum >> kDistanceAdjustLumShift];
             fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(color,
                                                                                 fViewMatrix,
                                                                                 fCurrTexture,
                                                                                 params,
-                                                                                fGammaTexture,
-                                                                                gammaParams,
-                                                                                lum/255.f,
+                                                                                correction,
                                                                                 flags,
                                                                                 opaque));
 #else
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
index b76be3d..1524a94 100644
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ b/src/gpu/GrDistanceFieldTextContext.h
@@ -36,11 +36,11 @@
     bool                               fUseLCDText;
     bool                               fEnableDFRendering;
     SkAutoTUnref<GrGeometryProcessor>  fCachedGeometryProcessor;
+    SkScalar*                          fDistanceAdjustTable;
     // Used to check whether fCachedEffect is still valid.
     uint32_t                           fEffectTextureUniqueID;
     SkColor                            fEffectColor;
     uint32_t                           fEffectFlags;
-    GrTexture*                         fGammaTexture;
     void*                              fVertices;
     int                                fCurrVertex;
     int                                fAllocVertexCount;
@@ -50,6 +50,7 @@
     SkMatrix                           fViewMatrix;
 
     GrDistanceFieldTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&, bool enable);
+    void buildDistanceAdjustTable();
 
     bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                  const SkPaint&, const SkMatrix& viewMatrix) override;
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 0acf1f3..d44c193 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -9,14 +9,16 @@
 #include "GrFontAtlasSizes.h"
 #include "GrInvariantOutput.h"
 #include "GrTexture.h"
+
 #include "SkDistanceFieldGen.h"
+
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLTexture.h"
 #include "gl/GrGLGeometryProcessor.h"
 #include "gl/builders/GrGLProgramBuilder.h"
 
-// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
+// Assuming a radius of a little less than the diagonal of the fragment
 #define SK_DistanceFieldAAFactor     "0.65"
 
 struct DistanceFieldBatchTracker {
@@ -31,7 +33,7 @@
                                    const GrBatchTracker&)
         : fColor(GrColor_ILLEGAL)
 #ifdef SK_GAMMA_APPLY_TO_A8
-        , fLuminance(-1.0f)
+        , fDistanceAdjust(-1.0f)
 #endif
         {}
 
@@ -59,6 +61,14 @@
         vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
                                GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
                                dfTexEffect.inTextureCoords()->fName);
+#ifdef SK_GAMMA_APPLY_TO_A8
+        // adjust based on gamma
+        const char* distanceAdjustUniName = NULL;
+        // width, height, 1/(3*width)
+        fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            kFloat_GrSLType, kDefault_GrSLPrecision,
+            "DistanceAdjust", &distanceAdjustUniName);
+#endif
 
         // Setup pass through color
         this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
@@ -83,6 +93,10 @@
         fsBuilder->codeAppend(".r;\n");
         fsBuilder->codeAppend("\tfloat distance = "
                        SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
+#ifdef SK_GAMMA_APPLY_TO_A8
+        // adjust width based on gamma
+        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
+#endif
 
         fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
                                                              pb->ctxInfo().standard()));
@@ -119,21 +133,6 @@
         }
         fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);");
 
-#ifdef SK_GAMMA_APPLY_TO_A8
-        // adjust based on gamma
-        const char* luminanceUniName = NULL;
-        // width, height, 1/(3*width)
-        fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                             kFloat_GrSLType, kDefault_GrSLPrecision,
-                                             "Luminance", &luminanceUniName);
-
-        fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
-        fsBuilder->codeAppend("\tvec4 gammaColor = ");
-        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
-        fsBuilder->codeAppend(";\n");
-        fsBuilder->codeAppend("\tval = gammaColor.r;\n");
-#endif
-
         fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
     }
 
@@ -143,10 +142,10 @@
 #ifdef SK_GAMMA_APPLY_TO_A8
         const GrDistanceFieldTextureEffect& dfTexEffect =
                 proc.cast<GrDistanceFieldTextureEffect>();
-        float luminance = dfTexEffect.getLuminance();
-        if (luminance != fLuminance) {
-            pdman.set1f(fLuminanceUni, luminance);
-            fLuminance = luminance;
+        float distanceAdjust = dfTexEffect.getDistanceAdjust();
+        if (distanceAdjust != fDistanceAdjust) {
+            pdman.set1f(fDistanceAdjustUni, distanceAdjust);
+            fDistanceAdjust = distanceAdjust;
         }
 #endif
 
@@ -178,8 +177,8 @@
     GrColor       fColor;
     UniformHandle fColorUniform;
 #ifdef SK_GAMMA_APPLY_TO_A8
-    UniformHandle fLuminanceUni;
-    float         fLuminance;
+    float         fDistanceAdjust;
+    UniformHandle fDistanceAdjustUni;
 #endif
 
     typedef GrGLGeometryProcessor INHERITED;
@@ -192,16 +191,13 @@
                                                            GrTexture* texture,
                                                            const GrTextureParams& params,
 #ifdef SK_GAMMA_APPLY_TO_A8
-                                                           GrTexture* gamma,
-                                                           const GrTextureParams& gammaParams,
-                                                           float luminance,
+                                                           float distanceAdjust,
 #endif
                                                            uint32_t flags, bool opaqueVertexColors)
     : INHERITED(color, viewMatrix, SkMatrix::I(), opaqueVertexColors)
     , fTextureAccess(texture, params)
 #ifdef SK_GAMMA_APPLY_TO_A8
-    , fGammaTextureAccess(gamma, gammaParams)
-    , fLuminance(luminance)
+    , fDistanceAdjust(distanceAdjust)
 #endif
     , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
     , fInColor(NULL) {
@@ -215,16 +211,13 @@
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
                                                           kVec2s_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
-#ifdef SK_GAMMA_APPLY_TO_A8
-    this->addTextureAccess(&fGammaTextureAccess);
-#endif
 }
 
 bool GrDistanceFieldTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
     const GrDistanceFieldTextureEffect& cte = other.cast<GrDistanceFieldTextureEffect>();
     return
 #ifdef SK_GAMMA_APPLY_TO_A8
-           fLuminance == cte.fLuminance &&
+           fDistanceAdjust == cte.fDistanceAdjust &&
 #endif
            fFlags == cte.fFlags;
 }
@@ -245,7 +238,8 @@
     return SkNEW_ARGS(GrGLDistanceFieldTextureEffect, (*this, bt));
 }
 
-void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const {
+void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt,
+                                                    const GrPipelineInfo& init) const {
     DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
     local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
                                                SkToBool(fInColor));
@@ -273,10 +267,6 @@
                                                               GrTexture* textures[]) {
     int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
                                       GrProcessorUnitTest::kAlphaTextureIdx;
-#ifdef SK_GAMMA_APPLY_TO_A8
-    int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
-                                       GrProcessorUnitTest::kAlphaTextureIdx;
-#endif
     static const SkShader::TileMode kTileModes[] = {
         SkShader::kClamp_TileMode,
         SkShader::kRepeat_TileMode,
@@ -288,16 +278,11 @@
     };
     GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
                                                            GrTextureParams::kNone_FilterMode);
-#ifdef SK_GAMMA_APPLY_TO_A8
-    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
-                                                            GrTextureParams::kNone_FilterMode);
-#endif
 
     return GrDistanceFieldTextureEffect::Create(GrRandomColor(random),
                                                 GrProcessorUnitTest::TestMatrix(random),
                                                 textures[texIdx], params,
 #ifdef SK_GAMMA_APPLY_TO_A8
-                                                textures[texIdx2], params2,
                                                 random->nextF(),
 #endif
                                                 random->nextBool() ?
@@ -487,7 +472,8 @@
     return fFlags == cte.fFlags;
 }
 
-void GrDistanceFieldNoGammaTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const{
+void GrDistanceFieldNoGammaTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out)
+                                                                                             const {
     out->setUnknownSingleComponent();
 }
 
@@ -563,8 +549,9 @@
 public:
     GrGLDistanceFieldLCDTextureEffect(const GrGeometryProcessor&,
                                       const GrBatchTracker&)
-    : fColor(GrColor_ILLEGAL)
-    , fTextColor(GrColor_ILLEGAL) {}
+        : fColor(GrColor_ILLEGAL) {
+        fDistanceAdjust = GrDistanceFieldLCDTextureEffect::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
+    }
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
         const GrDistanceFieldLCDTextureEffect& dfTexEffect =
@@ -650,6 +637,13 @@
         fsBuilder->codeAppend("\tdistance = "
            "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));");
 
+        // adjust width based on gamma
+        const char* distanceAdjustUniName = NULL;
+        fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+            kVec3f_GrSLType, kDefault_GrSLPrecision,
+            "DistanceAdjust", &distanceAdjustUniName);
+        fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
+
         // To be strictly correct, we should compute the anti-aliasing factor separately
         // for each color component. However, this is only important when using perspective
         // transformations, and even then using a single factor seems like a reasonable
@@ -682,31 +676,8 @@
             fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);");
         }
 
-        fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
-
-        // adjust based on gamma
-        const char* textColorUniName = NULL;
-        fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
-                                             kVec3f_GrSLType, kDefault_GrSLPrecision,
-                                             "TextColor", &textColorUniName);
-
-        fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
-        fsBuilder->codeAppend("float gammaColor = ");
-        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
-        fsBuilder->codeAppend(".r;\n");
-        fsBuilder->codeAppend("\tval.x = gammaColor;\n");
-
-        fsBuilder->codeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
-        fsBuilder->codeAppend("\tgammaColor = ");
-        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
-        fsBuilder->codeAppend(".r;\n");
-        fsBuilder->codeAppend("\tval.y = gammaColor;\n");
-
-        fsBuilder->codeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
-        fsBuilder->codeAppend("\tgammaColor = ");
-        fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType);
-        fsBuilder->codeAppend(".r;\n");
-        fsBuilder->codeAppend("\tval.z = gammaColor;\n");
+        fsBuilder->codeAppend(
+                      "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);");
 
         fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
     }
@@ -714,18 +685,17 @@
     virtual void setData(const GrGLProgramDataManager& pdman,
                          const GrPrimitiveProcessor& processor,
                          const GrBatchTracker& bt) override {
-        SkASSERT(fTextColorUni.isValid());
+        SkASSERT(fDistanceAdjustUni.isValid());
 
         const GrDistanceFieldLCDTextureEffect& dfTexEffect =
                 processor.cast<GrDistanceFieldLCDTextureEffect>();
-        GrColor textColor = dfTexEffect.getTextColor();
-        if (textColor != fTextColor) {
-            static const float ONE_OVER_255 = 1.f / 255.f;
-            pdman.set3f(fTextColorUni,
-                        GrColorUnpackR(textColor) * ONE_OVER_255,
-                        GrColorUnpackG(textColor) * ONE_OVER_255,
-                        GrColorUnpackB(textColor) * ONE_OVER_255);
-            fTextColor = textColor;
+        GrDistanceFieldLCDTextureEffect::DistanceAdjust wa = dfTexEffect.getDistanceAdjust();
+        if (wa != fDistanceAdjust) {
+            pdman.set3f(fDistanceAdjustUni,
+                        wa.fR,
+                        wa.fG,
+                        wa.fB);
+            fDistanceAdjust = wa;
         }
 
         this->setUniformViewMatrix(pdman, processor.viewMatrix());
@@ -755,10 +725,10 @@
     }
 
 private:
-    GrColor       fColor;
-    UniformHandle fColorUniform;
-    UniformHandle fTextColorUni;
-    SkColor       fTextColor;
+    GrColor                                      fColor;
+    UniformHandle                                fColorUniform;
+    GrDistanceFieldLCDTextureEffect::DistanceAdjust fDistanceAdjust;
+    UniformHandle                                fDistanceAdjustUni;
 
     typedef GrGLGeometryProcessor INHERITED;
 };
@@ -768,13 +738,11 @@
 GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
                                                   GrColor color, const SkMatrix& viewMatrix,
                                                   GrTexture* texture, const GrTextureParams& params,
-                                                  GrTexture* gamma, const GrTextureParams& gParams,
-                                                  SkColor textColor,
+                                                  DistanceAdjust distanceAdjust,
                                                   uint32_t flags)
     : INHERITED(color, viewMatrix, SkMatrix::I())
     , fTextureAccess(texture, params)
-    , fGammaTextureAccess(gamma, gParams)
-    , fTextColor(textColor)
+    , fDistanceAdjust(distanceAdjust)
     , fFlags(flags & kLCD_DistanceFieldEffectMask){
     SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
     this->initClassID<GrDistanceFieldLCDTextureEffect>();
@@ -782,16 +750,16 @@
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
                                                           kVec2s_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
-    this->addTextureAccess(&fGammaTextureAccess);
 }
 
 bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrGeometryProcessor& other) const {
     const GrDistanceFieldLCDTextureEffect& cte = other.cast<GrDistanceFieldLCDTextureEffect>();
-    return (fTextColor == cte.fTextColor &&
+    return (fDistanceAdjust == cte.fDistanceAdjust &&
             fFlags == cte.fFlags);
 }
 
-void GrDistanceFieldLCDTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
+void GrDistanceFieldLCDTextureEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out)
+                                                                                             const {
     out->setUnknownFourComponents();
     out->setUsingLCDCoverage();
 }
@@ -836,8 +804,6 @@
                                                                  GrTexture* textures[]) {
     int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
                                       GrProcessorUnitTest::kAlphaTextureIdx;
-    int texIdx2 = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
-                                       GrProcessorUnitTest::kAlphaTextureIdx;
     static const SkShader::TileMode kTileModes[] = {
         SkShader::kClamp_TileMode,
         SkShader::kRepeat_TileMode,
@@ -849,19 +815,13 @@
     };
     GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
                            GrTextureParams::kNone_FilterMode);
-    GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
-                           GrTextureParams::kNone_FilterMode);
-    GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
-                                        random->nextULessThan(256),
-                                        random->nextULessThan(256),
-                                        random->nextULessThan(256));
+    DistanceAdjust wa = { 0.0f, 0.1f, -0.1f };
     uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
     flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
     flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
     return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random),
                                                    GrProcessorUnitTest::TestMatrix(random),
                                                    textures[texIdx], params,
-                                                   textures[texIdx2], params2,
-                                                   textColor,
+                                                   wa,
                                                    flags);
 }
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h
index e05af76..6be7f9e 100644
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.h
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h
@@ -49,10 +49,8 @@
 #ifdef SK_GAMMA_APPLY_TO_A8
     static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex,
                                        const GrTextureParams& params,
-                                       GrTexture* gamma, const GrTextureParams& gammaParams,
                                        float lum, uint32_t flags, bool opaqueVertexColors) {
-       return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, gamma,
-                                                        gammaParams, lum,
+       return SkNEW_ARGS(GrDistanceFieldTextureEffect, (color, viewMatrix, tex, params, lum,
                                                         flags, opaqueVertexColors));
     }
 #else
@@ -72,7 +70,7 @@
     const Attribute* inColor() const { return fInColor; }
     const Attribute* inTextureCoords() const { return fInTextureCoords; }
 #ifdef SK_GAMMA_APPLY_TO_A8
-    float getLuminance() const { return fLuminance; }
+    float getDistanceAdjust() const { return fDistanceAdjust; }
 #endif
     uint32_t getFlags() const { return fFlags; }
 
@@ -93,7 +91,7 @@
     GrDistanceFieldTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture,
                                  const GrTextureParams& params,
 #ifdef SK_GAMMA_APPLY_TO_A8
-                                 GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
+                                 float distanceAdjust,
 #endif
                                  uint32_t flags, bool opaqueVertexColors);
 
@@ -101,12 +99,11 @@
 
     void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const override;
 
-    GrTextureAccess    fTextureAccess;
+    GrTextureAccess  fTextureAccess;
 #ifdef SK_GAMMA_APPLY_TO_A8
-    GrTextureAccess    fGammaTextureAccess;
-    float              fLuminance;
+    float            fDistanceAdjust;
 #endif
-    uint32_t           fFlags;
+    uint32_t         fFlags;
     const Attribute* fInPosition;
     const Attribute* fInColor;
     const Attribute* fInTextureCoords;
@@ -182,12 +179,26 @@
  */
 class GrDistanceFieldLCDTextureEffect : public GrGeometryProcessor {
 public:
+    struct DistanceAdjust {
+        SkScalar fR, fG, fB;
+        static DistanceAdjust Make(SkScalar r, SkScalar g, SkScalar b) {
+            DistanceAdjust result;
+            result.fR = r; result.fG = g; result.fB = b;
+            return result;
+        }
+        bool operator==(const DistanceAdjust& wa) const {
+            return (fR == wa.fR && fG == wa.fG && fB == wa.fB);
+        }
+        bool operator!=(const DistanceAdjust& wa) const {
+            return !(*this == wa);
+        }
+    };
+
     static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix, GrTexture* tex,
-                                       const GrTextureParams& params, GrTexture* gamma,
-                                       const GrTextureParams& gammaParams,
-                                       SkColor textColor, uint32_t flags) {
+                                       const GrTextureParams& params, 
+                                       DistanceAdjust distanceAdjust, uint32_t flags) {
         return SkNEW_ARGS(GrDistanceFieldLCDTextureEffect,
-                          (color, viewMatrix, tex, params, gamma, gammaParams, textColor, flags));
+                          (color, viewMatrix, tex, params, distanceAdjust, flags));
     }
 
     virtual ~GrDistanceFieldLCDTextureEffect() {}
@@ -196,7 +207,7 @@
 
     const Attribute* inPosition() const { return fInPosition; }
     const Attribute* inTextureCoords() const { return fInTextureCoords; }
-    GrColor getTextColor() const { return fTextColor; }
+    DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
     uint32_t getFlags() const { return fFlags; }
 
     virtual void getGLProcessorKey(const GrBatchTracker& bt,
@@ -215,17 +226,15 @@
 private:
     GrDistanceFieldLCDTextureEffect(GrColor, const SkMatrix& viewMatrix, GrTexture* texture,
                                     const GrTextureParams& params,
-                                    GrTexture* gamma, const GrTextureParams& gammaParams,
-                                    SkColor textColor, uint32_t flags);
+                                    DistanceAdjust wa, uint32_t flags);
 
     bool onIsEqual(const GrGeometryProcessor& other) const override;
 
     void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const override;
 
-    GrTextureAccess    fTextureAccess;
-    GrTextureAccess    fGammaTextureAccess;
-    GrColor            fTextColor;
-    uint32_t           fFlags;
+    GrTextureAccess  fTextureAccess;
+    DistanceAdjust   fDistanceAdjust;
+    uint32_t         fFlags;
     const Attribute* fInPosition;
     const Attribute* fInTextureCoords;