add SkLerpXfermode

BUG=
R=bsalomon@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk/include@9229 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/core/SkColorPriv.h b/core/SkColorPriv.h
index 46f7d27..5d2df62 100644
--- a/core/SkColorPriv.h
+++ b/core/SkColorPriv.h
@@ -273,16 +273,16 @@
  * architectures than an equivalent 64b version and 30% faster than
  * SkFourByteInterp(). Third parameter controls blending of the first two:
  *   (src, dst, 0) returns dst
- *   (src, dst, 0xFF) returns src
- * ** Does not match the results of SkFourByteInterp() because we use
+ *   (src, dst, 256) returns src
+ * ** Does not match the results of SkFourByteInterp256() because we use
  * a more accurate scale computation!
  * TODO: migrate Skia function to using an accurate 255->266 alpha
  * conversion.
  */
-static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
-                                             SkPMColor dst,
-                                             U8CPU srcWeight) {
-    SkASSERT(srcWeight < 256);
+static inline SkPMColor SkFastFourByteInterp256(SkPMColor src,
+                                                SkPMColor dst,
+                                                unsigned scale) {
+    SkASSERT(scale <= 256);
 
     // Reorders ARGB to AG-RB in order to reduce the number of operations.
     const uint32_t mask = 0xFF00FF;
@@ -291,16 +291,21 @@
     uint32_t dst_rb = dst & mask;
     uint32_t dst_ag = (dst >> 8) & mask;
 
-    // scale = srcWeight + (srcWeight >> 7) is more accurate than
-    // scale = srcWeight + 1, but 7% slower
-    int scale = srcWeight + (srcWeight >> 7);
-
     uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
     uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
 
     return (ret_ag & ~mask) | ((ret_rb & ~mask) >> 8);
 }
 
+static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
+                                             SkPMColor dst,
+                                             U8CPU srcWeight) {
+    SkASSERT(srcWeight <= 255);
+    // scale = srcWeight + (srcWeight >> 7) is more accurate than
+    // scale = srcWeight + 1, but 7% slower
+    return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
+}
+
 /**
  *  Same as SkPackARGB32, but this version guarantees to not check that the
  *  values are premultiplied in the debug version.
diff --git a/effects/SkLerpXfermode.h b/effects/SkLerpXfermode.h
new file mode 100644
index 0000000..6151f3d
--- /dev/null
+++ b/effects/SkLerpXfermode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLerpXfermode_DEFINED
+#define SkLerpXfermode_DEFINED
+
+#include "SkXfermode.h"
+
+class SK_API SkLerpXfermode : public SkXfermode {
+public:
+    /**
+     *  result = scale * src + (1 - scale) * dst
+     *
+     *  When scale == 1, this is the same as kSrc_Mode
+     *  When scale == 0, this is the same as kDst_Mode
+     */
+    static SkXfermode* Create(SkScalar scale);
+
+    // overrides from SkXfermode
+    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;
+
+    SK_DEVELOPER_TO_STRING()
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLerpXfermode)
+
+protected:
+    SkLerpXfermode(SkFlattenableReadBuffer&);
+    virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+
+private:
+    SkLerpXfermode(unsigned scale256);
+
+    unsigned fScale256;  // 0..256
+
+    typedef SkXfermode INHERITED;
+};
+
+#endif