Add flag to gradients to interpolate colors in premul space. Experimental API to encapsulate the shared parameters for all gradients into a struct.

BUG=
R=bsalomon@google.com

Review URL: https://codereview.chromium.org/15893002

git-svn-id: http://skia.googlecode.com/svn/trunk@9273 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/alphagradients.cpp b/gm/alphagradients.cpp
new file mode 100644
index 0000000..d335a9d
--- /dev/null
+++ b/gm/alphagradients.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkGradientShader.h"
+
+class AlphaGradientsGM : public skiagm::GM {
+public:
+    AlphaGradientsGM() {}
+
+protected:
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("alphagradients");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return SkISize::Make(640, 480);
+    }
+
+    static void draw_grad(SkCanvas* canvas, const SkRect& r,
+                          SkColor c0, SkColor c1, bool doPreMul) {
+        SkColor colors[] = { c0, c1 };
+        SkPoint pts[] = { { r.fLeft, r.fTop }, { r.fRight, r.fBottom } };
+        SkPaint paint;
+        uint32_t flags = doPreMul ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0;
+        SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2,
+                                                     SkShader::kClamp_TileMode,
+                                                     NULL, flags);
+        paint.setShader(s)->unref();
+        canvas->drawRect(r, paint);
+        
+        paint.setShader(NULL);
+        paint.setStyle(SkPaint::kStroke_Style);
+        canvas->drawRect(r, paint);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        static const struct {
+            SkColor fColor0;
+            SkColor fColor1;
+        } gRec[] = {
+            { 0xFFFFFFFF, 0x00000000 },
+            { 0xFFFFFFFF, 0x00FF0000 },
+            { 0xFFFFFFFF, 0x00FFFF00 },
+            { 0xFFFFFFFF, 0x00FFFFFF },
+            { 0xFFFF0000, 0x00000000 },
+            { 0xFFFF0000, 0x00FF0000 },
+            { 0xFFFF0000, 0x00FFFF00 },
+            { 0xFFFF0000, 0x00FFFFFF },
+            { 0xFF0000FF, 0x00000000 },
+            { 0xFF0000FF, 0x00FF0000 },
+            { 0xFF0000FF, 0x00FFFF00 },
+            { 0xFF0000FF, 0x00FFFFFF },
+        };
+    
+        SkRect r = SkRect::MakeWH(300, 30);
+        
+        canvas->translate(10, 10);
+
+        for (int doPreMul = 0; doPreMul <= 1; ++doPreMul) {
+            canvas->save();
+            for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
+                draw_grad(canvas, r, gRec[i].fColor0, gRec[i].fColor1, SkToBool(doPreMul));
+                canvas->translate(0, r.height() + 8);
+            }
+            canvas->restore();
+            canvas->translate(r.width() + 10, 0);
+        }
+    }
+
+    virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
+
+private:
+    typedef skiagm::GM INHERITED;
+};
+
+DEF_GM( return SkNEW(AlphaGradientsGM); )
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index d07820d..2cc188a 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -3,6 +3,7 @@
   'sources': [
     '../gm/aaclip.cpp',
     '../gm/aarectmodes.cpp',
+    '../gm/alphagradients.cpp',
     '../gm/arithmode.cpp',
     '../gm/bicubicfilter.cpp',
     '../gm/bigmatrix.cpp',
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 126602d..e1cab96 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -312,6 +312,7 @@
         SkPoint     fPoint[2];      //!< Type specific, see above.
         SkScalar    fRadius[2];     //!< Type specific, see above.
         TileMode    fTileMode;      //!< The tile mode used.
+        uint32_t    fGradientFlags; //!< see SkGradientShader::Flags
     };
 
     virtual GradientType asAGradient(GradientInfo* info) const;
diff --git a/include/effects/SkGradientShader.h b/include/effects/SkGradientShader.h
index dbeb2fb..ed0f1bf 100644
--- a/include/effects/SkGradientShader.h
+++ b/include/effects/SkGradientShader.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2006 The Android Open Source Project
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #ifndef SkGradientShader_DEFINED
 #define SkGradientShader_DEFINED
 
@@ -21,6 +19,15 @@
 */
 class SK_API SkGradientShader {
 public:
+    enum Flags {
+        /** By default gradients will interpolate their colors in unpremul space
+         *  and then premultiply each of the results. By setting this flag, the
+         *  gradients will premultiply their colors first, and then interpolate
+         *  between them.
+         */
+        kInterpolateColorsInPremul_Flag = 1 << 0,
+    };
+
     /** Returns a shader that generates a linear gradient between the two
         specified points.
         <p />
@@ -38,10 +45,11 @@
         @param  mode    The tiling mode
         @param  mapper  May be NULL. Callback to modify the spread of the colors.
     */
-    static SkShader* CreateLinear(  const SkPoint pts[2],
-                                    const SkColor colors[], const SkScalar pos[], int count,
-                                    SkShader::TileMode mode,
-                                    SkUnitMapper* mapper = NULL);
+    static SkShader* CreateLinear(const SkPoint pts[2],
+                                  const SkColor colors[], const SkScalar pos[], int count,
+                                  SkShader::TileMode mode,
+                                  SkUnitMapper* mapper = NULL,
+                                  uint32_t flags = 0);
 
     /** Returns a shader that generates a radial gradient given the center and radius.
         <p />
@@ -60,10 +68,11 @@
         @param  mode    The tiling mode
         @param  mapper  May be NULL. Callback to modify the spread of the colors.
     */
-    static SkShader* CreateRadial(  const SkPoint& center, SkScalar radius,
-                                    const SkColor colors[], const SkScalar pos[], int count,
-                                    SkShader::TileMode mode,
-                                    SkUnitMapper* mapper = NULL);
+    static SkShader* CreateRadial(const SkPoint& center, SkScalar radius,
+                                  const SkColor colors[], const SkScalar pos[], int count,
+                                  SkShader::TileMode mode,
+                                  SkUnitMapper* mapper = NULL,
+                                  uint32_t flags = 0);
 
     /** Returns a shader that generates a radial gradient given the start position, start radius, end position and end radius.
         <p />
@@ -92,7 +101,8 @@
                                           const SkColor colors[],
                                           const SkScalar pos[], int count,
                                           SkShader::TileMode mode,
-                                          SkUnitMapper* mapper = NULL);
+                                          SkUnitMapper* mapper = NULL,
+                                          uint32_t flags = 0);
 
     /**
      *  Returns a shader that generates a conical gradient given two circles, or
@@ -101,13 +111,14 @@
      *  http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
      */
     static SkShader* CreateTwoPointConical(const SkPoint& start,
-                                          SkScalar startRadius,
-                                          const SkPoint& end,
-                                          SkScalar endRadius,
-                                          const SkColor colors[],
-                                          const SkScalar pos[], int count,
-                                          SkShader::TileMode mode,
-                                          SkUnitMapper* mapper = NULL);
+                                           SkScalar startRadius,
+                                           const SkPoint& end,
+                                           SkScalar endRadius,
+                                           const SkColor colors[],
+                                           const SkScalar pos[], int count,
+                                           SkShader::TileMode mode,
+                                           SkUnitMapper* mapper = NULL,
+                                           uint32_t flags = 0);
 
     /** Returns a shader that generates a sweep gradient given a center.
         <p />
@@ -127,7 +138,8 @@
     */
     static SkShader* CreateSweep(SkScalar cx, SkScalar cy,
                                  const SkColor colors[], const SkScalar pos[],
-                                 int count, SkUnitMapper* mapper = NULL);
+                                 int count, SkUnitMapper* mapper = NULL,
+                                 uint32_t flags = 0);
 
     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
 };
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index d1ab539..6dcbb05 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -19,6 +19,7 @@
 
     fMapper = desc.fMapper;
     SkSafeRef(fMapper);
+    fGradFlags = SkToU8(desc.fFlags);
 
     SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
     SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
@@ -128,8 +129,21 @@
     this->initCommon();
 }
 
-SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) :
-    INHERITED(buffer) {
+static uint32_t pack_mode_flags(SkShader::TileMode mode, uint32_t flags) {
+    SkASSERT(0 == (flags >> 28));
+    SkASSERT(0 == ((uint32_t)mode >> 4));
+    return (flags << 4) | mode;
+}
+
+static SkShader::TileMode unpack_mode(uint32_t packed) {
+    return (SkShader::TileMode)(packed & 0xF);
+}
+
+static uint32_t unpack_flags(uint32_t packed) {
+    return packed >> 4;
+}
+
+SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
     fCacheAlpha = 256;
 
     fMapper = buffer.readFlattenableT<SkUnitMapper>();
@@ -147,7 +161,11 @@
     }
     buffer.readColorArray(fOrigColors);
 
-    fTileMode = (TileMode)buffer.readUInt();
+    {
+        uint32_t packed = buffer.readUInt();
+        fGradFlags = SkToU8(unpack_flags(packed));
+        fTileMode = unpack_mode(packed);
+    }
     fTileProc = gTileProcs[fTileMode];
     fRecs = (Rec*)(fOrigColors + colorCount);
     if (colorCount > 2) {
@@ -186,7 +204,7 @@
     this->INHERITED::flatten(buffer);
     buffer.writeFlattenable(fMapper);
     buffer.writeColorArray(fOrigColors, fColorCount);
-    buffer.writeUInt(fTileMode);
+    buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags));
     if (fColorCount > 2) {
         Rec* recs = fRecs;
         for (int i = 1; i < fColorCount; i++) {
@@ -288,39 +306,58 @@
     } while (--count != 0);
 }
 
+/*
+ *  r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
+ *  release builds, we saw a compiler error where the 0xFF parameter in
+ *  SkPackARGB32() was being totally ignored whenever it was called with
+ *  a non-zero add (e.g. 0x8000).
+ *
+ *  We found two work-arounds:
+ *      1. change r,g,b to unsigned (or just one of them)
+ *      2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
+ *         of using |
+ *
+ *  We chose #1 just because it was more localized.
+ *  See http://code.google.com/p/skia/issues/detail?id=1113
+ *
+ *  The type SkUFixed encapsulate this need for unsigned, but logically Fixed.
+ */
+typedef uint32_t SkUFixed;
+
 void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
-                                      int count, U8CPU paintAlpha) {
+                                      int count, U8CPU paintAlpha, uint32_t gradFlags) {
     SkASSERT(count > 1);
 
     // need to apply paintAlpha to our two endpoints
-    SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
-    SkFixed da;
-    {
-        int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
-        da = SkIntToFixed(tmp - a) / (count - 1);
+    uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
+    uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
+
+
+    const bool interpInPremul = SkToBool(gradFlags &
+                           SkGradientShader::kInterpolateColorsInPremul_Flag);
+
+    uint32_t r0 = SkColorGetR(c0);
+    uint32_t g0 = SkColorGetG(c0);
+    uint32_t b0 = SkColorGetB(c0);
+
+    uint32_t r1 = SkColorGetR(c1);
+    uint32_t g1 = SkColorGetG(c1);
+    uint32_t b1 = SkColorGetB(c1);
+
+    if (interpInPremul) {
+        r0 = SkMulDiv255Round(r0, a0);
+        g0 = SkMulDiv255Round(g0, a0);
+        b0 = SkMulDiv255Round(b0, a0);
+
+        r1 = SkMulDiv255Round(r1, a1);
+        g1 = SkMulDiv255Round(g1, a1);
+        b1 = SkMulDiv255Round(b1, a1);
     }
 
-    /*
-     *  r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
-     *  release builds, we saw a compiler error where the 0xFF parameter in
-     *  SkPackARGB32() was being totally ignored whenever it was called with
-     *  a non-zero add (e.g. 0x8000).
-     *
-     *  We found two work-arounds:
-     *      1. change r,g,b to unsigned (or just one of them)
-     *      2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
-     *         of using |
-     *
-     *  We chose #1 just because it was more localized.
-     *  See http://code.google.com/p/skia/issues/detail?id=1113
-     */
-    uint32_t r = SkColorGetR(c0);
-    uint32_t g = SkColorGetG(c0);
-    uint32_t b = SkColorGetB(c0);
-
-    SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
-    SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
-    SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
+    SkFixed da = SkIntToFixed(a1 - a0) / (count - 1);
+    SkFixed dr = SkIntToFixed(r1 - r0) / (count - 1);
+    SkFixed dg = SkIntToFixed(g1 - g0) / (count - 1);
+    SkFixed db = SkIntToFixed(b1 - b0) / (count - 1);
 
     /*  We pre-add 1/8 to avoid having to add this to our [0] value each time
         in the loop. Without this, the bias for each would be
@@ -328,9 +365,10 @@
         With this trick, we can add 0 for the first (no-op) and just adjust the
         others.
      */
-    r = SkIntToFixed(r) + 0x2000;
-    g = SkIntToFixed(g) + 0x2000;
-    b = SkIntToFixed(b) + 0x2000;
+    SkUFixed a = SkIntToFixed(a0) + 0x2000;
+    SkUFixed r = SkIntToFixed(r0) + 0x2000;
+    SkUFixed g = SkIntToFixed(g0) + 0x2000;
+    SkUFixed b = SkIntToFixed(b0) + 0x2000;
 
     /*
      *  Our dither-cell (spatially) is
@@ -343,7 +381,7 @@
      *      [3] -> [ 5/8 ... 7/8 ) values near 3/4
      */
 
-    if (0xFF == a && 0 == da) {
+    if (0xFF == a0 && 0 == da) {
         do {
             cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0     ) >> 16,
                                                         (g + 0     ) >> 16,
@@ -362,8 +400,31 @@
             g += dg;
             b += db;
         } while (--count != 0);
-    } else {
-        a = SkIntToFixed(a) + 0x2000;
+    } else if (interpInPremul) {
+        do {
+            cache[kCache32Count*0] = SkPackARGB32((a + 0     ) >> 16,
+                                                  (r + 0     ) >> 16,
+                                                  (g + 0     ) >> 16,
+                                                  (b + 0     ) >> 16);
+            cache[kCache32Count*1] = SkPackARGB32((a + 0x8000) >> 16,
+                                                  (r + 0x8000) >> 16,
+                                                  (g + 0x8000) >> 16,
+                                                  (b + 0x8000) >> 16);
+            cache[kCache32Count*2] = SkPackARGB32((a + 0xC000) >> 16,
+                                                  (r + 0xC000) >> 16,
+                                                  (g + 0xC000) >> 16,
+                                                  (b + 0xC000) >> 16);
+            cache[kCache32Count*3] = SkPackARGB32((a + 0x4000) >> 16,
+                                                  (r + 0x4000) >> 16,
+                                                  (g + 0x4000) >> 16,
+                                                  (b + 0x4000) >> 16);
+            cache += 1;
+            a += da;
+            r += dr;
+            g += dg;
+            b += db;
+        } while (--count != 0);
+    } else {    // interpolate in unpreml space
         do {
             cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0     ) >> 16,
                                                              (r + 0     ) >> 16,
@@ -463,7 +524,7 @@
         fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
         if (fColorCount == 2) {
             Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
-                            kCache32Count, fCacheAlpha);
+                            kCache32Count, fCacheAlpha, fGradFlags);
         } else {
             Rec* rec = fRecs;
             int prevIndex = 0;
@@ -473,8 +534,8 @@
 
                 if (nextIndex > prevIndex)
                     Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
-                                    fOrigColors[i],
-                                    nextIndex - prevIndex + 1, fCacheAlpha);
+                                    fOrigColors[i], nextIndex - prevIndex + 1,
+                                    fCacheAlpha, fGradFlags);
                 prevIndex = nextIndex;
             }
         }
@@ -522,8 +583,8 @@
         return;
     }
 
-    // build our key: [numColors + colors[] + {positions[]} ]
-    int count = 1 + fColorCount;
+    // build our key: [numColors + colors[] + {positions[]} + flags ]
+    int count = 1 + fColorCount + 1;
     if (fColorCount > 2) {
         count += fColorCount - 1;    // fRecs[].fPos
     }
@@ -539,6 +600,7 @@
             *buffer++ = fRecs[i].fPos;
         }
     }
+    *buffer++ = fGradFlags;
     SkASSERT(buffer - storage.get() == count);
 
     ///////////////////////////////////
@@ -583,6 +645,7 @@
         }
         info->fColorCount = fColorCount;
         info->fTileMode = fTileMode;
+        info->fGradientFlags = fGradFlags;
     }
 }
 
@@ -643,26 +706,28 @@
                       const SkColor colors[],
                       const SkScalar pos[], int colorCount,
                       SkShader::TileMode mode,
-                      SkUnitMapper* mapper) {
+                      SkUnitMapper* mapper, uint32_t flags) {
     desc->fColors   = colors;
     desc->fPos      = pos;
     desc->fCount    = colorCount;
     desc->fTileMode = mode;
     desc->fMapper   = mapper;
+    desc->fFlags    = flags;
 }
 
 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
                                          const SkColor colors[],
                                          const SkScalar pos[], int colorCount,
                                          SkShader::TileMode mode,
-                                         SkUnitMapper* mapper) {
+                                         SkUnitMapper* mapper,
+                                         uint32_t flags) {
     if (NULL == pts || NULL == colors || colorCount < 1) {
         return NULL;
     }
     EXPAND_1_COLOR(colorCount);
 
     SkGradientShaderBase::Descriptor desc;
-    desc_init(&desc, colors, pos, colorCount, mode, mapper);
+    desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
     return SkNEW_ARGS(SkLinearGradient, (pts, desc));
 }
 
@@ -670,14 +735,15 @@
                                          const SkColor colors[],
                                          const SkScalar pos[], int colorCount,
                                          SkShader::TileMode mode,
-                                         SkUnitMapper* mapper) {
+                                         SkUnitMapper* mapper,
+                                         uint32_t flags) {
     if (radius <= 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
     EXPAND_1_COLOR(colorCount);
 
     SkGradientShaderBase::Descriptor desc;
-    desc_init(&desc, colors, pos, colorCount, mode, mapper);
+    desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
     return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
 }
 
@@ -689,27 +755,29 @@
                                                  const SkScalar pos[],
                                                  int colorCount,
                                                  SkShader::TileMode mode,
-                                                 SkUnitMapper* mapper) {
+                                                 SkUnitMapper* mapper,
+                                                 uint32_t flags) {
     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
     EXPAND_1_COLOR(colorCount);
 
     SkGradientShaderBase::Descriptor desc;
-    desc_init(&desc, colors, pos, colorCount, mode, mapper);
+    desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
     return SkNEW_ARGS(SkTwoPointRadialGradient,
                       (start, startRadius, end, endRadius, desc));
 }
 
 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
-                                                 SkScalar startRadius,
-                                                 const SkPoint& end,
-                                                 SkScalar endRadius,
-                                                 const SkColor colors[],
-                                                 const SkScalar pos[],
-                                                 int colorCount,
-                                                 SkShader::TileMode mode,
-                                                 SkUnitMapper* mapper) {
+                                                  SkScalar startRadius,
+                                                  const SkPoint& end,
+                                                  SkScalar endRadius,
+                                                  const SkColor colors[],
+                                                  const SkScalar pos[],
+                                                  int colorCount,
+                                                  SkShader::TileMode mode,
+                                                  SkUnitMapper* mapper,
+                                                  uint32_t flags) {
     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -719,7 +787,7 @@
     EXPAND_1_COLOR(colorCount);
 
     SkGradientShaderBase::Descriptor desc;
-    desc_init(&desc, colors, pos, colorCount, mode, mapper);
+    desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
     return SkNEW_ARGS(SkTwoPointConicalGradient,
                       (start, startRadius, end, endRadius, desc));
 }
@@ -727,14 +795,15 @@
 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
                                         const SkColor colors[],
                                         const SkScalar pos[],
-                                        int colorCount, SkUnitMapper* mapper) {
+                                        int colorCount, SkUnitMapper* mapper,
+                                        uint32_t flags) {
     if (NULL == colors || colorCount < 1) {
         return NULL;
     }
     EXPAND_1_COLOR(colorCount);
 
     SkGradientShaderBase::Descriptor desc;
-    desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper);
+    desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
     return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
 }
 
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index d792c42..31cc9f2 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -93,6 +93,7 @@
         int                 fCount;
         SkShader::TileMode  fTileMode;
         SkUnitMapper*       fMapper;
+        uint32_t            fFlags;
     };
 
 public:
@@ -141,6 +142,7 @@
     int         fColorCount;
     uint8_t     fDstToIndexClass;
     uint8_t     fFlags;
+    uint8_t     fGradFlags;
 
     struct Rec {
         SkFixed     fPos;   // 0...1
@@ -172,7 +174,7 @@
 
     static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
     static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
-                                U8CPU alpha);
+                                U8CPU alpha, uint32_t gradFlags);
     void setCacheAlpha(U8CPU alpha) const;
     void initCommon();
 
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 51433af..f975a18 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -10,8 +10,8 @@
 
 SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy,
                                  const Descriptor& desc)
-: SkGradientShaderBase(desc),
-  fCenter(SkPoint::Make(cx, cy))
+    : SkGradientShaderBase(desc)
+    , fCenter(SkPoint::Make(cx, cy))
 {
     fPtsToUnit.setTranslate(-cx, -cy);
 
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 0066942..37b49f0 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -175,9 +175,9 @@
 /////////////////////////////////////////////////////////////////////
 
 SkTwoPointConicalGradient::SkTwoPointConicalGradient(
-    const SkPoint& start, SkScalar startRadius,
-    const SkPoint& end, SkScalar endRadius,
-    const Descriptor& desc)
+        const SkPoint& start, SkScalar startRadius,
+        const SkPoint& end, SkScalar endRadius,
+        const Descriptor& desc)
     : SkGradientShaderBase(desc),
     fCenter1(start),
     fCenter2(end),