Orphan ProcXfermode, with an eye towards removing it

BUG=skia:
R=scroggo@google.com, mtklein@google.com

Author: reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14238 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 32a544c..fb17268 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -775,6 +775,7 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+#ifdef SK_SUPPORT_LEGACY_PROCXFERMODE
 
 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
                             const SkPMColor* SK_RESTRICT src, int count,
@@ -884,6 +885,7 @@
 }
 #endif
 
+#endif
 //////////////////////////////////////////////////////////////////////////////
 
 #if SK_SUPPORT_GPU
@@ -1358,11 +1360,10 @@
     fMode = (SkXfermode::Mode)mode32;
 
     const ProcCoeff& rec = gProcCoeffs[fMode];
+    fProc = rec.fProc;
     // these may be valid, or may be CANNOT_USE_COEFF
     fSrcCoeff = rec.fSC;
     fDstCoeff = rec.fDC;
-    // now update our function-ptr in the super class
-    this->INHERITED::setProc(rec.fProc);
 }
 
 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
@@ -1386,6 +1387,93 @@
     return true;
 }
 
+void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
+                                 const SkPMColor* SK_RESTRICT src, int count,
+                                 const SkAlpha* SK_RESTRICT aa) const {
+    SkASSERT(dst && src && count >= 0);
+    
+    SkXfermodeProc proc = fProc;
+    
+    if (NULL != proc) {
+        if (NULL == aa) {
+            for (int i = count - 1; i >= 0; --i) {
+                dst[i] = proc(src[i], dst[i]);
+            }
+        } else {
+            for (int i = count - 1; i >= 0; --i) {
+                unsigned a = aa[i];
+                if (0 != a) {
+                    SkPMColor dstC = dst[i];
+                    SkPMColor C = proc(src[i], dstC);
+                    if (a != 0xFF) {
+                        C = SkFourByteInterp(C, dstC, a);
+                    }
+                    dst[i] = C;
+                }
+            }
+        }
+    }
+}
+
+void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
+                                 const SkPMColor* SK_RESTRICT src, int count,
+                                 const SkAlpha* SK_RESTRICT aa) const {
+    SkASSERT(dst && src && count >= 0);
+    
+    SkXfermodeProc proc = fProc;
+    
+    if (NULL != proc) {
+        if (NULL == aa) {
+            for (int i = count - 1; i >= 0; --i) {
+                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
+                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
+            }
+        } else {
+            for (int i = count - 1; i >= 0; --i) {
+                unsigned a = aa[i];
+                if (0 != a) {
+                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
+                    SkPMColor C = proc(src[i], dstC);
+                    if (0xFF != a) {
+                        C = SkFourByteInterp(C, dstC, a);
+                    }
+                    dst[i] = SkPixel32ToPixel16_ToU16(C);
+                }
+            }
+        }
+    }
+}
+
+void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
+                                 const SkPMColor* SK_RESTRICT src, int count,
+                                 const SkAlpha* SK_RESTRICT aa) const {
+    SkASSERT(dst && src && count >= 0);
+    
+    SkXfermodeProc proc = fProc;
+    
+    if (NULL != proc) {
+        if (NULL == aa) {
+            for (int i = count - 1; i >= 0; --i) {
+                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
+                dst[i] = SkToU8(SkGetPackedA32(res));
+            }
+        } else {
+            for (int i = count - 1; i >= 0; --i) {
+                unsigned a = aa[i];
+                if (0 != a) {
+                    SkAlpha dstA = dst[i];
+                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
+                    unsigned A = SkGetPackedA32(res);
+                    if (0xFF != a) {
+                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
+                    }
+                    dst[i] = SkToU8(A);
+                }
+            }
+        }
+    }
+}
+
 #if SK_SUPPORT_GPU
 bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
                                       GrTexture* background) const {
diff --git a/src/core/SkXfermode_proccoeff.h b/src/core/SkXfermode_proccoeff.h
index 977c3da..7edf665 100644
--- a/src/core/SkXfermode_proccoeff.h
+++ b/src/core/SkXfermode_proccoeff.h
@@ -13,12 +13,19 @@
 
 #define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
 
-class SK_API SkProcCoeffXfermode : public SkProcXfermode {
+class SK_API SkProcCoeffXfermode : public SkXfermode {
 public:
     static SkProcCoeffXfermode* Create(const ProcCoeff& rec, Mode mode) {
         return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
     }
 
+    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const SK_OVERRIDE;
+    virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const SK_OVERRIDE;
+    virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+                        const SkAlpha aa[]) const SK_OVERRIDE;
+
     virtual bool asMode(Mode* mode) const SK_OVERRIDE;
 
     virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE;
@@ -32,9 +39,9 @@
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
 
 protected:
-    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
-            : INHERITED(rec.fProc) {
+    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) {
         fMode = mode;
+        fProc = rec.fProc;
         // these may be valid, or may be CANNOT_USE_COEFF
         fSrcCoeff = rec.fSC;
         fDstCoeff = rec.fDC;
@@ -44,15 +51,16 @@
 
     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
 
-    Mode getMode() const {
-        return fMode;
-    }
+    Mode getMode() const { return fMode; }
+
+    SkXfermodeProc getProc() const { return fProc; }
 
 private:
-    Mode    fMode;
-    Coeff   fSrcCoeff, fDstCoeff;
+    SkXfermodeProc  fProc;
+    Mode            fMode;
+    Coeff           fSrcCoeff, fDstCoeff;
 
-    typedef SkProcXfermode INHERITED;
+    typedef SkXfermode INHERITED;
 };
 
 #endif // #ifndef SkXfermode_proccoeff_DEFINED
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index 0f2b9e0..22eef6f 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -92,37 +92,45 @@
     return layer;
 }
 
-static SkPMColor OverdrawXferModeProc(SkPMColor src, SkPMColor dst) {
-    // This table encodes the color progression of the overdraw visualization
-    static const SkPMColor gTable[] = {
-        SkPackARGB32(0x00, 0x00, 0x00, 0x00),
-        SkPackARGB32(0xFF, 128, 158, 255),
-        SkPackARGB32(0xFF, 170, 185, 212),
-        SkPackARGB32(0xFF, 213, 195, 170),
-        SkPackARGB32(0xFF, 255, 192, 127),
-        SkPackARGB32(0xFF, 255, 185, 85),
-        SkPackARGB32(0xFF, 255, 165, 42),
-        SkPackARGB32(0xFF, 255, 135, 0),
-        SkPackARGB32(0xFF, 255,  95, 0),
-        SkPackARGB32(0xFF, 255,  50, 0),
-        SkPackARGB32(0xFF, 255,  0, 0)
-    };
-
-    for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
-        if (gTable[i] == dst) {
-            return gTable[i+1];
+class OverdrawXfermode : public SkXfermode {
+public:
+    virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const SK_OVERRIDE {
+        // This table encodes the color progression of the overdraw visualization
+        static const SkPMColor gTable[] = {
+            SkPackARGB32(0x00, 0x00, 0x00, 0x00),
+            SkPackARGB32(0xFF, 128, 158, 255),
+            SkPackARGB32(0xFF, 170, 185, 212),
+            SkPackARGB32(0xFF, 213, 195, 170),
+            SkPackARGB32(0xFF, 255, 192, 127),
+            SkPackARGB32(0xFF, 255, 185, 85),
+            SkPackARGB32(0xFF, 255, 165, 42),
+            SkPackARGB32(0xFF, 255, 135, 0),
+            SkPackARGB32(0xFF, 255,  95, 0),
+            SkPackARGB32(0xFF, 255,  50, 0),
+            SkPackARGB32(0xFF, 255,  0, 0)
+        };
+        
+        for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
+            if (gTable[i] == dst) {
+                return gTable[i+1];
+            }
         }
+        
+        return gTable[SK_ARRAY_COUNT(gTable)-1];
     }
 
-    return gTable[SK_ARRAY_COUNT(gTable)-1];
-}
+    virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
+#ifndef SK_IGNORE_TO_STRING
+    virtual void toString(SkString* str) const { str->set("OverdrawXfermode"); }
+#endif
+};
 
 // The OverdrawFilter modifies every paint to use an SkProcXfermode which
 // in turn invokes OverdrawXferModeProc
 class SkOverdrawFilter : public SkDrawFilter {
 public:
     SkOverdrawFilter() {
-        fXferMode = SkProcXfermode::Create(OverdrawXferModeProc);
+        fXferMode = SkNEW(OverdrawXfermode);
     }
 
     virtual ~SkOverdrawFilter() {