refactor lighting imagefilter to save codesize

Goal was to just remove template args and add virtuals where needed.
Ended up having to also move a couple of classes/helpers earlier in the file, but nothing beyond that.

Size savings (on Mac laptop) : 67896

Before:
   8/8   MB	1	30.6ms	30.7ms	30.7ms	30.9ms	0%	█▁▅▁▄▃▄▁▃▃	8888	lightingspotlitspecular_large
   8/8   MB	1	34.2ms	37.6ms	38.5ms	45.9ms	9%	▂▂▃▅▁▅█▂▅▂	8888	lightingspotlitspecular_small
   8/8   MB	1	31.3ms	35ms	34.6ms	38.4ms	7%	▁▄▅▆▆▁▇▃▂█	8888	lightingdistantlitspecular_large
   8/8   MB	1	29.9ms	33.5ms	34.3ms	39.2ms	8%	▁▅█▃▄▇▄▂▄▆	8888	lightingdistantlitspecular_small
   8/8   MB	1	30.4ms	34.1ms	34.5ms	40.7ms	11%	▂▄█▃▁▅▂▅▁▇	8888	lightingpointlitspecular_large
   8/8   MB	1	29.8ms	36.2ms	34.8ms	41.4ms	12%	▂▃▅▁▅▇▂▁▆█	8888	lightingpointlitspecular_small
   8/8   MB	1	16.3ms	19.5ms	20.5ms	26.6ms	17%	▁▆▃▃█▃▂▅▁▆	8888	lightingspotlitdiffuse_large
   8/8   MB	1	17.3ms	19.3ms	19.4ms	23.3ms	10%	▄▁▂▁▆▅▁▃▂█	8888	lightingspotlitdiffuse_small
   8/8   MB	1	12.7ms	14.9ms	17ms	27.9ms	30%	▂▁█▁▂▄▂▂▂▆	8888	lightingdistantlitdiffuse_large
   8/8   MB	1	12.4ms	14.5ms	15.8ms	24.7ms	23%	▁▂▅▂▁▃█▂▃▂	8888	lightingdistantlitdiffuse_small
   8/8   MB	1	13.6ms	14.9ms	16.6ms	22.5ms	22%	▁█▅▁▆▂▁▂▁█	8888	lightingpointlitdiffuse_large
   8/8   MB	1	13.8ms	17ms	16.5ms	19.2ms	11%	▆▆▁▁▆▅▅█▃▂	8888	lightingpointlitdiffuse_small

After:
   8/8   MB	1	23.5ms	23.6ms	23.8ms	25.1ms	2%	▃▁█▁▁▂▁▂▁▁	8888	lightingspotlitspecular_large
   8/8   MB	1	23.5ms	23.6ms	23.9ms	24.9ms	2%	█▅▂▁▁▁▁▁▆▃	8888	lightingspotlitspecular_small
   8/8   MB	1	21.6ms	21.8ms	21.9ms	22.3ms	1%	█▆▃▁▄▄▃▂▄▂	8888	lightingdistantlitspecular_large
   8/8   MB	1	21.6ms	21.7ms	21.9ms	22.7ms	2%	█▅▂▂▂▁▂▂▂▃	8888	lightingdistantlitspecular_small
   8/8   MB	1	22.3ms	22.9ms	22.8ms	23.2ms	1%	▇▆▁▄▆▄▃█▄▆	8888	lightingpointlitspecular_large
   8/8   MB	1	22.1ms	22.2ms	22.5ms	23.6ms	3%	██▁▁▂▂▁▁▂▂	8888	lightingpointlitspecular_small
   8/8   MB	1	12.8ms	13ms	13ms	13.3ms	2%	▃▇█▇▁▅▄▃▂▄	8888	lightingspotlitdiffuse_large
   8/8   MB	1	12.8ms	13ms	13ms	13.2ms	1%	▄▃██▄▁▃▅▂▇	8888	lightingspotlitdiffuse_small
   8/8   MB	1	10.6ms	10.7ms	10.8ms	11.1ms	2%	▂▄██▂▁▃▃▂▂	8888	lightingdistantlitdiffuse_large
   8/8   MB	1	10.6ms	10.7ms	10.8ms	11.3ms	2%	▂▂▇█▃▁▂▅▁▂	8888	lightingdistantlitdiffuse_small
   8/8   MB	1	10.9ms	11.1ms	11.2ms	11.6ms	2%	▁▂▇▁█▃▂▂▇▁	8888	lightingpointlitdiffuse_large
   8/8   MB	1	10.9ms	11.1ms	11.1ms	11.5ms	2%	▄▃█▅▃▃▁▃▂▁	8888	lightingpointlitdiffuse_small

Bug: skia:
Change-Id: I7542a5ca1f209a732630f646b4ceb4fb08150ce4
Reviewed-on: https://skia-review.googlesource.com/20155
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index fe6a39a..78f5899 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -77,12 +77,83 @@
     vector->fZ *= scale;
 }
 
-class DiffuseLightingType {
+static SkPoint3 readPoint3(SkReadBuffer& buffer) {
+    SkPoint3 point;
+    point.fX = buffer.readScalar();
+    point.fY = buffer.readScalar();
+    point.fZ = buffer.readScalar();
+    buffer.validate(SkScalarIsFinite(point.fX) &&
+                    SkScalarIsFinite(point.fY) &&
+                    SkScalarIsFinite(point.fZ));
+    return point;
+};
+
+static void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
+    buffer.writeScalar(point.fX);
+    buffer.writeScalar(point.fY);
+    buffer.writeScalar(point.fZ);
+};
+
+class GrGLLight;
+class SkImageFilterLight : public SkRefCnt {
+public:
+    enum LightType {
+        kDistant_LightType,
+        kPoint_LightType,
+        kSpot_LightType,
+    };
+    virtual LightType type() const = 0;
+    const SkPoint3& color() const { return fColor; }
+    virtual GrGLLight* createGLLight() const = 0;
+    virtual bool isEqual(const SkImageFilterLight& other) const {
+        return fColor == other.fColor;
+    }
+    virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
+
+    virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) const = 0;
+
+    // Defined below SkLight's subclasses.
+    void flattenLight(SkWriteBuffer& buffer) const;
+    static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
+
+    virtual SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const = 0;
+    virtual SkPoint3 lightColor(const SkPoint3& surfaceToLight) const = 0;
+
+protected:
+    SkImageFilterLight(SkColor color) {
+        fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
+                                SkIntToScalar(SkColorGetG(color)),
+                                SkIntToScalar(SkColorGetB(color)));
+    }
+    SkImageFilterLight(const SkPoint3& color)
+    : fColor(color) {}
+    SkImageFilterLight(SkReadBuffer& buffer) {
+        fColor = readPoint3(buffer);
+    }
+
+    virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
+
+
+private:
+    typedef SkRefCnt INHERITED;
+    SkPoint3 fColor;
+};
+
+class BaseLightingType {
+public:
+    BaseLightingType() {}
+    virtual ~BaseLightingType() {}
+
+    virtual SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
+                            const SkPoint3& lightColor) const= 0;
+};
+
+class DiffuseLightingType : public BaseLightingType {
 public:
     DiffuseLightingType(SkScalar kd)
         : fKD(kd) {}
     SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
-                    const SkPoint3& lightColor) const {
+                    const SkPoint3& lightColor) const override {
         SkScalar colorScale = fKD * normal.dot(surfaceTolight);
         colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
         SkPoint3 color = lightColor.makeScale(colorScale);
@@ -99,12 +170,12 @@
     return p.x() > p.y() ? (p.x() > p.z() ? p.x() : p.z()) : (p.y() > p.z() ? p.y() : p.z());
 }
 
-class SpecularLightingType {
+class SpecularLightingType : public BaseLightingType {
 public:
     SpecularLightingType(SkScalar ks, SkScalar shininess)
         : fKS(ks), fShininess(shininess) {}
     SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
-                    const SkPoint3& lightColor) const {
+                    const SkPoint3& lightColor) const override {
         SkPoint3 halfDir(surfaceTolight);
         halfDir.fZ += SK_Scalar1;        // eye position is always (0, 0, 1)
         fast_normalize(&halfDir);
@@ -206,15 +277,14 @@
     }
 };
 
-template <class LightingType, class LightType, class PixelFetcher>
-static void lightBitmap(const LightingType& lightingType,
-                 const SkImageFilterLight* light,
+template <class PixelFetcher>
+static void lightBitmap(const BaseLightingType& lightingType,
+                 const SkImageFilterLight* l,
                  const SkBitmap& src,
                  SkBitmap* dst,
                  SkScalar surfaceScale,
                  const SkIRect& bounds) {
     SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
-    const LightType* l = static_cast<const LightType*>(light);
     int left = bounds.left(), right = bounds.right();
     int bottom = bounds.bottom();
     int y = bounds.top();
@@ -298,39 +368,21 @@
     }
 }
 
-template <class LightingType, class LightType>
-static void lightBitmap(const LightingType& lightingType,
+static void lightBitmap(const BaseLightingType& lightingType,
                  const SkImageFilterLight* light,
                  const SkBitmap& src,
                  SkBitmap* dst,
                  SkScalar surfaceScale,
                  const SkIRect& bounds) {
     if (src.bounds().contains(bounds)) {
-        lightBitmap<LightingType, LightType, UncheckedPixelFetcher>(
+        lightBitmap<UncheckedPixelFetcher>(
             lightingType, light, src, dst, surfaceScale, bounds);
     } else {
-        lightBitmap<LightingType, LightType, DecalPixelFetcher>(
+        lightBitmap<DecalPixelFetcher>(
             lightingType, light, src, dst, surfaceScale, bounds);
     }
 }
 
-static SkPoint3 readPoint3(SkReadBuffer& buffer) {
-    SkPoint3 point;
-    point.fX = buffer.readScalar();
-    point.fY = buffer.readScalar();
-    point.fZ = buffer.readScalar();
-    buffer.validate(SkScalarIsFinite(point.fX) &&
-                    SkScalarIsFinite(point.fY) &&
-                    SkScalarIsFinite(point.fZ));
-    return point;
-};
-
-static void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
-    buffer.writeScalar(point.fX);
-    buffer.writeScalar(point.fY);
-    buffer.writeScalar(point.fZ);
-};
-
 enum BoundaryMode {
     kTopLeft_BoundaryMode,
     kTop_BoundaryMode,
@@ -751,47 +803,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-class SkImageFilterLight : public SkRefCnt {
-public:
-    enum LightType {
-        kDistant_LightType,
-        kPoint_LightType,
-        kSpot_LightType,
-    };
-    virtual LightType type() const = 0;
-    const SkPoint3& color() const { return fColor; }
-    virtual GrGLLight* createGLLight() const = 0;
-    virtual bool isEqual(const SkImageFilterLight& other) const {
-        return fColor == other.fColor;
-    }
-    virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
-
-    virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) const = 0;
-
-    // Defined below SkLight's subclasses.
-    void flattenLight(SkWriteBuffer& buffer) const;
-    static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
-
-protected:
-    SkImageFilterLight(SkColor color) {
-        fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
-                                SkIntToScalar(SkColorGetG(color)),
-                                SkIntToScalar(SkColorGetB(color)));
-    }
-    SkImageFilterLight(const SkPoint3& color)
-      : fColor(color) {}
-    SkImageFilterLight(SkReadBuffer& buffer) {
-        fColor = readPoint3(buffer);
-    }
-
-    virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
-
-
-private:
-    typedef SkRefCnt INHERITED;
-    SkPoint3 fColor;
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static SkColor xform_color(const SkPoint3& color, SkColorSpaceXformer* xformer) {
@@ -808,10 +819,10 @@
       : INHERITED(color), fDirection(direction) {
     }
 
-    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
+    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
         return fDirection;
     }
-    const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
+    SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
     LightType type() const override { return kDistant_LightType; }
     const SkPoint3& direction() const { return fDirection; }
     GrGLLight* createGLLight() const override {
@@ -865,14 +876,14 @@
     SkPointLight(const SkPoint3& location, SkColor color)
      : INHERITED(color), fLocation(location) {}
 
-    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
+    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
                                             fLocation.fY - SkIntToScalar(y),
                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
         fast_normalize(&direction);
         return direction;
     }
-    const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
+    SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
     LightType type() const override { return kPoint_LightType; }
     const SkPoint3& location() const { return fLocation; }
     GrGLLight* createGLLight() const override {
@@ -979,14 +990,14 @@
                                color());
     }
 
-    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
+    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
                                             fLocation.fY - SkIntToScalar(y),
                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
         fast_normalize(&direction);
         return direction;
     }
-    SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
+    SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
         SkScalar cosAngle = -surfaceToLight.dot(fS);
         SkScalar scale = 0;
         if (cosAngle >= fCosOuterConeAngle) {
@@ -1316,32 +1327,12 @@
     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
 
     DiffuseLightingType lightingType(fKD);
-    switch (transformedLight->type()) {
-        case SkImageFilterLight::kDistant_LightType:
-            lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType,
+    lightBitmap(lightingType,
                                                              transformedLight.get(),
                                                              inputBM,
                                                              &dst,
                                                              surfaceScale(),
                                                              bounds);
-            break;
-        case SkImageFilterLight::kPoint_LightType:
-            lightBitmap<DiffuseLightingType, SkPointLight>(lightingType,
-                                                           transformedLight.get(),
-                                                           inputBM,
-                                                           &dst,
-                                                           surfaceScale(),
-                                                           bounds);
-            break;
-        case SkImageFilterLight::kSpot_LightType:
-            lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType,
-                                                          transformedLight.get(),
-                                                          inputBM,
-                                                          &dst,
-                                                          surfaceScale(),
-                                                          bounds);
-            break;
-    }
 
     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                           dst);
@@ -1490,32 +1481,12 @@
 
     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
 
-    switch (transformedLight->type()) {
-        case SkImageFilterLight::kDistant_LightType:
-            lightBitmap<SpecularLightingType, SkDistantLight>(lightingType,
+    lightBitmap(lightingType,
                                                               transformedLight.get(),
                                                               inputBM,
                                                               &dst,
                                                               surfaceScale(),
                                                               bounds);
-            break;
-        case SkImageFilterLight::kPoint_LightType:
-            lightBitmap<SpecularLightingType, SkPointLight>(lightingType,
-                                                            transformedLight.get(),
-                                                            inputBM,
-                                                            &dst,
-                                                            surfaceScale(),
-                                                            bounds);
-            break;
-        case SkImageFilterLight::kSpot_LightType:
-            lightBitmap<SpecularLightingType, SkSpotLight>(lightingType,
-                                                           transformedLight.get(),
-                                                           inputBM,
-                                                           &dst,
-                                                           surfaceScale(),
-                                                           bounds);
-            break;
-    }
 
     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst);
 }