Revert "replace Arithmetic xfermode with imagefilter"

This reverts commit Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4.

Reason for revert: need to guard the no-gpu codepath

Original issue's description:
> replace Arithmetic xfermode with imagefilter
> 
> chrome pre-cl: https://codereview.chromium.org/2369023002/
> 
> BUG=skia:
> 
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2595
> 
> Change-Id: Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4
> Reviewed-on: https://skia-review.googlesource.com/2595
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
> 

TBR=robertphillips@google.com,fmalita@chromium.org,fmalita@google.com,reed@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Change-Id: I761799b594a0379c6bf356e6abc73552c3d19480
Reviewed-on: https://skia-review.googlesource.com/2661
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp
index 60879d6..7d00f41 100644
--- a/bench/XfermodeBench.cpp
+++ b/bench/XfermodeBench.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "Benchmark.h"
+#include "SkArithmeticMode.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
 #include "SkRandom.h"
@@ -22,6 +23,12 @@
         fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : "");
     }
 
+    XfermodeBench(sk_sp<SkXfermode> xferMode, const char* name, bool aa) {
+        fXfermode = xferMode;
+        fAA = aa;
+        fName.printf("Xfermode_%s%s", name, aa ? "_aa" : "");
+    }
+
 protected:
     const char* onGetName() override { return fName.c_str(); }
 
@@ -128,4 +135,13 @@
 BENCH(SkXfermode::kColor_Mode)
 BENCH(SkXfermode::kLuminosity_Mode)
 
+DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \
+                                    "arithmetic", false); )
+DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \
+                                    "arithmetic_enforce_pm", false); )
+DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \
+                                    "arithmetic", true); )
+DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \
+                                    "arithmetic_enforce_pm", true); )
+
 DEF_BENCH(return new XferCreateBench;)
diff --git a/gm/aaxfermodes.cpp b/gm/aaxfermodes.cpp
index 678a837..78f7d3e 100644
--- a/gm/aaxfermodes.cpp
+++ b/gm/aaxfermodes.cpp
@@ -39,11 +39,13 @@
     kLast_Shape = kConcave_Shape
 };
 
+namespace skiagm {
+
 /**
  * Verifies AA works properly on all Xfermodes, including arithmetic, with both opaque and unknown
  * src colors.
  */
-class AAXfermodesGM : public skiagm::GM {
+class AAXfermodesGM : public GM {
 public:
     AAXfermodesGM() {}
 
@@ -118,9 +120,6 @@
             canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2);
 
             for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) {
-                if (firstMode + m > SkXfermode::kLastMode) {
-                    break;
-                }
                 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode + m);
                 canvas->save();
 
@@ -211,7 +210,7 @@
             if (maxSum > 255) {
                 SkPaint dimPaint;
                 dimPaint.setAntiAlias(false);
-                dimPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+                dimPaint.setXfermode(SkXfermode::Make(SkXfermode::kDstIn_Mode));
                 if (255 != paint->getAlpha()) {
                     // Dim the src and dst colors.
                     dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0);
@@ -228,10 +227,16 @@
     }
 
     void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermode::Mode mode) {
-        SkASSERT(mode <= SkXfermode::kLastMode);
         SkPaint shapePaint(paint);
         shapePaint.setAntiAlias(kSquare_Shape != shape);
-        shapePaint.setXfermodeMode(mode);
+
+        sk_sp<SkXfermode> xfermode;
+        if (mode <= SkXfermode::kLastMode) {
+            xfermode = SkXfermode::Make(mode);
+        } else {
+            xfermode = SkArithmeticMode::Make(+1.0f, +0.25f, -0.5f, +0.1f);
+        }
+        shapePaint.setXfermode(std::move(xfermode));
 
         switch (shape) {
             case kSquare_Shape:
@@ -268,6 +273,12 @@
     SkPath    fOval;
     SkPath    fConcave;
 
-    typedef skiagm::GM INHERITED;
+    typedef GM INHERITED;
 };
-DEF_GM( return new AAXfermodesGM; )
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new AAXfermodesGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/arithmode.cpp b/gm/arithmode.cpp
index f98fbf7..70661a0 100644
--- a/gm/arithmode.cpp
+++ b/gm/arithmode.cpp
@@ -15,7 +15,6 @@
 #define WW  100
 #define HH  32
 
-#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE
 static SkBitmap make_bm() {
     SkBitmap bm;
     bm.allocN32Pixels(WW, HH);
@@ -161,4 +160,3 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 DEF_GM( return new ArithmodeGM; )
-#endif
diff --git a/gm/imagefiltersgraph.cpp b/gm/imagefiltersgraph.cpp
index 9803989..0f3dcd1 100644
--- a/gm/imagefiltersgraph.cpp
+++ b/gm/imagefiltersgraph.cpp
@@ -7,6 +7,7 @@
 
 #include "gm.h"
 
+#include "SkArithmeticMode.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorFilter.h"
 #include "SkColorFilterImageFilter.h"
@@ -89,7 +90,7 @@
 
             SkPaint paint;
             paint.setImageFilter(
-                SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true,
+                SkXfermodeImageFilter::Make(SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
                                             std::move(matrixFilter),
                                             std::move(offsetFilter),
                                             nullptr));
diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp
index a0677c7..0ff0ea9 100644
--- a/gm/xfermodeimagefilter.cpp
+++ b/gm/xfermodeimagefilter.cpp
@@ -7,6 +7,7 @@
 
 #include "gm.h"
 #include "sk_tool_utils.h"
+#include "SkArithmeticMode.h"
 #include "SkImage.h"
 #include "SkImageSource.h"
 #include "SkOffsetImageFilter.h"
@@ -96,7 +97,9 @@
             }
         }
         // Test arithmetic mode as image filter
-        paint.setImageFilter(SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true, background));
+        paint.setImageFilter(SkXfermodeImageFilter::Make(
+                         SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
+                         background));
         DrawClippedBitmap(canvas, fBitmap, paint, x, y);
         x += fBitmap.width() + MARGIN;
         if (x + fBitmap.width() > WIDTH) {
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
index 8fbbdbe..68d267b 100644
--- a/gm/xfermodes.cpp
+++ b/gm/xfermodes.cpp
@@ -11,6 +11,31 @@
 #include "SkXfermode.h"
 #include "SkPM4f.h"
 
+#include "SkArithmeticMode.h"
+
+#define kCustomShift    16
+#define kCustomMask     (~0xFFFF)
+
+enum CustomModes {
+    kArithmetic_CustomMode  = 1 << kCustomShift,
+};
+
+static sk_sp<SkXfermode> make_custom(int customMode) {
+    switch (customMode) {
+        case kArithmetic_CustomMode: {
+            const SkScalar k1 = 0.25;
+            const SkScalar k2 = 0.75;
+            const SkScalar k3 = 0.75;
+            const SkScalar k4 = -0.25;
+            return SkArithmeticMode::Make(k1, k2, k3, k4);
+        }
+        default:
+            break;
+    }
+    SkASSERT(false);
+    return nullptr;
+}
+
 enum SrcType {
     //! A WxH image with a rectangle in the lower right.
     kRectangleImage_SrcType               = 0x01,
@@ -73,6 +98,8 @@
     { SkXfermode::kSaturation_Mode,   "Saturation",   kBasic_SrcType },
     { SkXfermode::kColor_Mode,        "Color",        kBasic_SrcType },
     { SkXfermode::kLuminosity_Mode,   "Luminosity",   kBasic_SrcType },
+
+    { SkXfermode::Mode(0xFFFF),       "Arithmetic",   kBasic_SrcType + kArithmetic_CustomMode   },
 };
 
 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst,
@@ -118,7 +145,7 @@
      * uses the implied shape of the drawing command and these modes
      * demonstrate that.
      */
-    void draw_mode(SkCanvas* canvas, SkXfermode::Mode mode, SrcType srcType,
+    void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, SrcType srcType,
                    SkScalar x, SkScalar y) {
         SkPaint p;
         SkMatrix m;
@@ -126,7 +153,7 @@
         m.setTranslate(x, y);
 
         canvas->drawBitmap(fSrcB, x, y, &p);
-        p.setXfermodeMode(mode);
+        p.setXfermode(std::move(mode));
         switch (srcType) {
             case kSmallTransparentImage_SrcType: {
                 m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y);
@@ -214,7 +241,7 @@
     }
 
     SkISize onISize() override {
-        return SkISize::Make(1990, 570);
+        return SkISize::Make(1990, 660);
     }
 
     void onDraw(SkCanvas* canvas) override {
@@ -242,7 +269,14 @@
                 if ((gModes[i].fSourceTypeMask & sourceType) == 0) {
                     continue;
                 }
-                SkRect r{ x, y, x+w, y+h };
+                sk_sp<SkXfermode> mode;
+                if (gModes[i].fSourceTypeMask & kCustomMask) {
+                    mode = make_custom(gModes[i].fSourceTypeMask & kCustomMask);
+                } else {
+                    mode = SkXfermode::Make(gModes[i].fMode);
+                }
+                SkRect r;
+                r.set(x, y, x+w, y+h);
 
                 SkPaint p;
                 p.setStyle(SkPaint::kFill_Style);
@@ -250,7 +284,7 @@
                 canvas->drawRect(r, p);
 
                 canvas->saveLayer(&r, nullptr);
-                draw_mode(canvas, gModes[i].fMode, static_cast<SrcType>(sourceType),
+                draw_mode(canvas, std::move(mode), static_cast<SrcType>(sourceType),
                           r.fLeft, r.fTop);
                 canvas->restore();
 
diff --git a/include/effects/SkArithmeticMode.h b/include/effects/SkArithmeticMode.h
index 81b9f85..b160dc7 100644
--- a/include/effects/SkArithmeticMode.h
+++ b/include/effects/SkArithmeticMode.h
@@ -12,8 +12,6 @@
 #include "SkScalar.h"
 #include "SkXfermode.h"
 
-#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE
-
 class SK_API SkArithmeticMode {
 public:
     /**
@@ -40,5 +38,3 @@
 };
 
 #endif
-
-#endif
diff --git a/include/effects/SkXfermodeImageFilter.h b/include/effects/SkXfermodeImageFilter.h
index 6066b8d..e391575 100644
--- a/include/effects/SkXfermodeImageFilter.h
+++ b/include/effects/SkXfermodeImageFilter.h
@@ -26,18 +26,6 @@
         return Make(std::move(mode), std::move(background), nullptr, nullptr);
     }
 
-    static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4,
-                                               bool enforcePMColor,
-                                               sk_sp<SkImageFilter> background,
-                                               sk_sp<SkImageFilter> foreground,
-                                               const SkImageFilter::CropRect* cropRect);
-    static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4,
-                                               bool enforcePMColor,
-                                               sk_sp<SkImageFilter> background) {
-        return MakeArithmetic(k1, k2, k3, k4, enforcePMColor, std::move(background),
-                              nullptr, nullptr);
-    }
-
 #ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
     static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
                                  SkImageFilter* foreground = NULL,
diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp
index 876f34b..b8aa368 100644
--- a/src/effects/SkArithmeticMode.cpp
+++ b/src/effects/SkArithmeticMode.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "SkArithmeticModePriv.h"
+#include "SkArithmeticMode.h"
 #include "SkColorPriv.h"
 #include "SkNx.h"
 #include "SkRasterPipeline.h"
diff --git a/src/effects/SkArithmeticModePriv.h b/src/effects/SkArithmeticModePriv.h
deleted file mode 100644
index 04bd90e..0000000
--- a/src/effects/SkArithmeticModePriv.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkArithmeticModePriv_DEFINED
-#define SkArithmeticModePriv_DEFINED
-
-#include "SkArithmeticMode.h"
-
-#ifndef SK_SUPPORT_LEGACY_ARITHMETICMODE
-
-class SK_API SkArithmeticMode {
-public:
-    /**
-     *  result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4]
-     *
-     *  k1=k2=k3=0, k4=1.0 results in returning opaque white
-     *  k1=k3=k4=0, k2=1.0 results in returning the src
-     *  k1=k2=k4=0, k3=1.0 results in returning the dst
-     */
-    static sk_sp<SkXfermode> Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
-                                  bool enforcePMColor = true);
-#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
-    static SkXfermode* Create(SkScalar k1, SkScalar k2,
-                              SkScalar k3, SkScalar k4,
-                              bool enforcePMColor = true) {
-        return Make(k1, k2, k3, k4, enforcePMColor).release();
-    }
-#endif
-
-    SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
-
-private:
-    SkArithmeticMode(); // can't be instantiated
-};
-
-#endif
-
-#endif
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 655c48c..c602a4a 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -20,12 +20,11 @@
 #include "effects/GrConstColorProcessor.h"
 #include "effects/GrTextureDomain.h"
 #include "effects/GrSimpleTextureEffect.h"
-#include "SkArithmeticMode_gpu.h"
 #include "SkGr.h"
 #include "SkGrPriv.h"
 #endif
 
-class SkXfermodeImageFilter_Base : public SkImageFilter {
+class SK_API SkXfermodeImageFilter_Base : public SkImageFilter {
 public:
     SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2],
                                const CropRect* cropRect);
@@ -49,8 +48,6 @@
 
     void flatten(SkWriteBuffer&) const override;
 
-    virtual void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const;
-    virtual sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const;
 
 private:
     sk_sp<SkXfermode> fMode;
@@ -141,33 +138,31 @@
     SkASSERT(canvas);
 
     canvas->clear(0x0); // can't count on background to fully clear the background
+
     canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
 
+    SkPaint paint;
+    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
     if (background) {
-        SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
         background->draw(canvas,
                          SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
                          &paint);
     }
 
-    this->drawForeground(canvas, foreground.get(), foregroundBounds);
-
-    return surf->makeImageSnapshot();
-}
-
-void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
-                                                const SkIRect& fgBounds) const {
-    SkPaint paint;
     paint.setXfermode(fMode);
-    if (img) {
-        img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
+
+    if (foreground) {
+        foreground->draw(canvas,
+                         SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY),
+                         &paint);
     }
 
-    SkAutoCanvasRestore acr(canvas, true);
-    canvas->clipRect(SkRect::Make(fgBounds), SkCanvas::kDifference_Op);
-    paint.setColor(0);
+    canvas->clipRect(SkRect::Make(foregroundBounds), SkCanvas::kDifference_Op);
+    paint.setColor(SK_ColorTRANSPARENT);
     canvas->drawPaint(paint);
+
+    return surf->makeImageSnapshot();
 }
 
 #ifndef SK_IGNORE_TO_STRING
@@ -254,7 +249,21 @@
 
         paint.addColorFragmentProcessor(std::move(foregroundFP));
 
-        sk_sp<GrFragmentProcessor> xferFP = this->makeFGFrag(bgFP);
+        // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
+        SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
+        if (!mode) {
+            // It would be awesome to use SkXfermode::Create here but it knows better
+            // than us and won't return a kSrcOver_Mode SkXfermode. That means we
+            // have to get one the hard way.
+            struct ProcCoeff rec;
+            rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
+            SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
+
+            mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
+        }
+
+        sk_sp<GrFragmentProcessor> xferFP(
+            mode->makeFragmentProcessorForImageFilter(std::move(bgFP)));
 
         // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
         if (xferFP) {
@@ -285,220 +294,13 @@
                                        sk_ref_sp(drawContext->getColorSpace()));
 }
 
-sk_sp<GrFragmentProcessor>
-SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const {
-    // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
-    SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
-    if (!mode) {
-        // It would be awesome to use SkXfermode::Create here but it knows better
-        // than us and won't return a kSrcOver_Mode SkXfermode. That means we
-        // have to get one the hard way.
-        struct ProcCoeff rec;
-        rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
-        SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
-
-        mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
-    }
-    return mode->makeFragmentProcessorForImageFilter(std::move(bgFP));
-}
-
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-class SkArithmeticImageFilter : public SkXfermodeImageFilter_Base {
-public:
-    SkArithmeticImageFilter(float k1, float k2, float k3, float k4, bool enforcePMColor,
-                            sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect)
-        : SkXfermodeImageFilter_Base(nullptr, inputs, cropRect)
-        , fK{ k1, k2, k3, k4 }
-        , fEnforcePMColor(enforcePMColor)
-    {}
-
-    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticImageFilter)
-
-protected:
-    void flatten(SkWriteBuffer& buffer) const override {
-        this->INHERITED::flatten(buffer);
-        for (int i = 0; i < 4; ++i) {
-            buffer.writeScalar(fK[i]);
-        }
-        buffer.writeBool(fEnforcePMColor);
-    }
-    void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const override;
-    sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const override;
-
-private:
-    const float fK[4];
-    const bool fEnforcePMColor;
-
-    friend class SkXfermodeImageFilter;
-
-    typedef SkXfermodeImageFilter_Base INHERITED;
-};
-
-sk_sp<SkFlattenable> SkArithmeticImageFilter::CreateProc(SkReadBuffer& buffer) {
-    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
-
-    // skip the mode (srcover) our parent-class wrote
-    sk_sp<SkXfermode> mode(buffer.readXfermode());
-    SkASSERT(nullptr == mode);
-
-    float k[4];
-    for (int i = 0; i < 4; ++i) {
-        k[i] = buffer.readScalar();
-    }
-    const bool enforcePMColor = buffer.readBool();
-    return SkXfermodeImageFilter::MakeArithmetic(k[0], k[1], k[2], k[3], enforcePMColor,
-                                                 common.getInput(0), common.getInput(1),
-                                                 &common.cropRect());
-}
-
-#include "SkNx.h"
-
-static Sk4f pin(float min, const Sk4f& val, float max) {
-    return Sk4f::Max(min, Sk4f::Min(val, max));
-}
-
-template<bool EnforcePMColor> void arith_span(const float k[], SkPMColor dst[],
-                                              const SkPMColor src[], int count) {
-    const Sk4f k1 = k[0] * (1/255.0f),
-               k2 = k[1],
-               k3 = k[2],
-               k4 = k[3] * 255.0f + 0.5f;
-
-    for (int i = 0; i < count; i++) {
-        Sk4f s = SkNx_cast<float>(Sk4b::Load(src+i)),
-        d = SkNx_cast<float>(Sk4b::Load(dst+i)),
-        r = pin(0, k1*s*d + k2*s + k3*d + k4, 255);
-        if (EnforcePMColor) {
-            Sk4f a = SkNx_shuffle<3,3,3,3>(r);
-            r = Sk4f::Min(a, r);
-        }
-        SkNx_cast<uint8_t>(r).store(dst+i);
-    }
-}
-
-// apply mode to src==transparent (0)
-template<bool EnforcePMColor> void arith_transparent(const float k[], SkPMColor dst[], int count) {
-    const Sk4f k3 = k[2],
-               k4 = k[3] * 255.0f + 0.5f;
-
-    for (int i = 0; i < count; i++) {
-        Sk4f d = SkNx_cast<float>(Sk4b::Load(dst+i)),
-             r = pin(0, k3*d + k4, 255);
-        if (EnforcePMColor) {
-            Sk4f a = SkNx_shuffle<3,3,3,3>(r);
-            r = Sk4f::Min(a, r);
-        }
-        SkNx_cast<uint8_t>(r).store(dst+i);
-    }
-}
-
-static bool intersect(SkPixmap* dst, SkPixmap* src, SkIPoint srcOffset) {
-    SkIRect dstR = SkIRect::MakeWH(dst->width(), dst->height());
-    SkIRect srcR = SkIRect::MakeXYWH(srcOffset.x(), srcOffset.y(), src->width(), src->height());
-    SkIRect sect;
-    if (!sect.intersect(dstR, srcR)) {
-        return false;
-    }
-    *dst = SkPixmap(dst->info().makeWH(sect.width(), sect.height()),
-                    dst->addr(sect.fLeft, sect.fTop),
-                    dst->rowBytes());
-    *src = SkPixmap(src->info().makeWH(sect.width(), sect.height()),
-                    src->addr(SkTMax(0, -srcOffset.x()), SkTMax(0, -srcOffset.y())),
-                    src->rowBytes());
-    return true;
-}
-
-void SkArithmeticImageFilter::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
-                                             const SkIRect& fgBounds) const {
-    SkPixmap dst;
-    if (!canvas->peekPixels(&dst)) {
-        return;
-    }
-
-    if (img) {
-        SkBitmap srcBM;
-        SkPixmap src;
-        if (!img->getROPixels(&srcBM)) {
-            return;
-        }
-        srcBM.lockPixels();
-        if (!srcBM.peekPixels(&src)) {
-            return;
-        }
-
-        auto proc = fEnforcePMColor ? arith_span<true> : arith_span<false>;
-        const SkMatrix& ctm = canvas->getTotalMatrix();
-        SkASSERT(ctm.getType() <= SkMatrix::kTranslate_Mask);
-        SkIPoint offset {
-            fgBounds.fLeft + SkScalarRoundToInt(ctm.getTranslateX()),
-            fgBounds.fTop  + SkScalarRoundToInt(ctm.getTranslateY()),
-        };
-        SkPixmap tmpDst = dst;
-        if (intersect(&tmpDst, &src, offset)) {
-            for (int y = 0; y < tmpDst.height(); ++y) {
-                proc(fK, tmpDst.writable_addr32(0, y), src.addr32(0, y), tmpDst.width());
-            }
-        }
-    }
-
-    // Now apply the mode with transparent-color to the outside of the fg image
-    SkRegion outside(SkIRect::MakeWH(dst.width(), dst.height()));
-    outside.op(fgBounds, SkRegion::kDifference_Op);
-    auto proc = fEnforcePMColor ? arith_transparent<true> : arith_transparent<false>;
-    for (SkRegion::Iterator iter(outside); !iter.done(); iter.next()) {
-        const SkIRect r = iter.rect();
-        for (int y = r.fTop; y < r.fBottom; ++y) {
-            proc(fK, dst.writable_addr32(r.fLeft, y), r.width());
-        }
-    }
-}
-
-sk_sp<GrFragmentProcessor>
-SkArithmeticImageFilter::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const {
-    return GrArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP));
-}
-
-sk_sp<SkImageFilter> SkXfermodeImageFilter::MakeArithmetic(float k1, float k2, float k3, float k4,
-                                                           bool enforcePMColor,
-                                                           sk_sp<SkImageFilter> background,
-                                                           sk_sp<SkImageFilter> foreground,
-                                                           const SkImageFilter::CropRect* crop) {
-    if (!SkScalarIsFinite(k1) || !SkScalarIsFinite(k2) ||
-        !SkScalarIsFinite(k3) || !SkScalarIsFinite(k4)) {
-        return nullptr;
-    }
-
-    // are we nearly some other "std" mode?
-    int mode = -1;  // illegal mode
-    if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
-        SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kSrc_Mode;
-    } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
-               SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kDst_Mode;
-    } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
-               SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
-        mode = SkXfermode::kClear_Mode;
-    }
-    if (mode >= 0) {
-        return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode),
-                                           std::move(background), std::move(foreground), crop);
-    }
-
-    sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
-    return sk_sp<SkImageFilter>(new SkArithmeticImageFilter(k1, k2, k3, k4, enforcePMColor,
-                                                            inputs, crop));
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermodeImageFilter)
     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base)
     // manually register the legacy serialized name "SkXfermodeImageFilter"
     SkFlattenable::Register("SkXfermodeImageFilter", SkXfermodeImageFilter_Base::CreateProc,
                             SkFlattenable::kSkImageFilter_Type);
-    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticImageFilter)
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp
index 499e9bf..be41422 100644
--- a/src/ports/SkGlobalInitialization_default.cpp
+++ b/src/ports/SkGlobalInitialization_default.cpp
@@ -8,7 +8,7 @@
 #include "Sk1DPathEffect.h"
 #include "Sk2DPathEffect.h"
 #include "SkAlphaThresholdFilter.h"
-#include "../../src/effects/SkArithmeticModePriv.h"
+#include "SkArithmeticMode.h"
 #include "SkArcToPathEffect.h"
 #include "SkBitmapSourceDeserializer.h"
 #include "SkBlurDrawLooper.h"