Added PointLights to SkLights::Light

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2237493002

Review-Url: https://codereview.chromium.org/2237493002
diff --git a/gm/lightingshader.cpp b/gm/lightingshader.cpp
index 54318ee..4a79ebe 100644
--- a/gm/lightingshader.cpp
+++ b/gm/lightingshader.cpp
@@ -48,11 +48,11 @@
 
         SkLights::Builder builder;
 
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
-                                    SkVector3::Make(SK_ScalarRoot2Over2,
-                                                    0.0f,
-                                                    SK_ScalarRoot2Over2)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
+                                                     SkVector3::Make(SK_ScalarRoot2Over2,
+                                                                     0.0f,
+                                                                     SK_ScalarRoot2Over2)));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
 
         fLights = builder.finish();
     }
diff --git a/gm/lightingshader2.cpp b/gm/lightingshader2.cpp
index 5e0d19b..70c9e29 100644
--- a/gm/lightingshader2.cpp
+++ b/gm/lightingshader2.cpp
@@ -43,9 +43,9 @@
         SkLights::Builder builder;
         const SkVector3 kLightFromUpperRight = SkVector3::Make(0.788f, 0.394f, 0.473f);
 
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
-                                    kLightFromUpperRight));
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
+                                                     kLightFromUpperRight));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
         fLights = builder.finish();
 
         fRect = SkRect::MakeIWH(kTexSize, kTexSize);
diff --git a/gm/lightingshaderbevel.cpp b/gm/lightingshaderbevel.cpp
index dfc46e4..9107cc6 100644
--- a/gm/lightingshaderbevel.cpp
+++ b/gm/lightingshaderbevel.cpp
@@ -36,9 +36,9 @@
         SkLights::Builder builder;
         const SkVector3 kLightFromUpperRight = SkVector3::Make(0.788f, 0.394f, 0.473f);
 
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
-                                    kLightFromUpperRight));
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
+                                                     kLightFromUpperRight));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
         fLights = builder.finish();
 
         // fRect is assumed to be square throughout this file
diff --git a/gm/shadowmaps.cpp b/gm/shadowmaps.cpp
index b343d9b..f953550 100644
--- a/gm/shadowmaps.cpp
+++ b/gm/shadowmaps.cpp
@@ -70,11 +70,11 @@
         //   - soft white ambient light
 
         SkLights::Builder builder;
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f),
-                                    SkVector3::Make(0.2f, 0.1f, 1.0f)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f),
-                                    SkVector3::Make(0.1f, 0.2f, 1.0f)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.2f, 0.3f, 0.4f),
+                                                     SkVector3::Make(0.2f, 0.1f, 1.0f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.4f, 0.3f, 0.2f),
+                                                     SkVector3::Make(0.1f, 0.2f, 1.0f)));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
         fLights = builder.finish();
     }
 
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 13b7ef6..8d1dc8d 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -152,6 +152,7 @@
         '<(skia_src_path)/core/SkImageGeneratorPriv.h',
         '<(skia_src_path)/core/SkLightingShader.h',
         '<(skia_src_path)/core/SkLightingShader.cpp',
+        '<(skia_src_path)/core/SkLights.cpp',
         '<(skia_src_path)/core/SkLinearBitmapPipeline.cpp',
         '<(skia_src_path)/core/SkLinearBitmapPipeline.h',
         '<(skia_src_path)/core/SkLinearBitmapPipeline_core.h',
diff --git a/include/core/SkLights.h b/include/core/SkLights.h
index 52e60c7..d9ec65b 100644
--- a/include/core/SkLights.h
+++ b/include/core/SkLights.h
@@ -9,10 +9,13 @@
 #ifndef SkLights_DEFINED
 #define SkLights_DEFINED
 
+#include "../private/SkTArray.h"
 #include "SkPoint3.h"
 #include "SkRefCnt.h"
-#include "../private/SkTArray.h"
-#include "SkImage.h"
+
+class SkReadBuffer;
+class SkWriteBuffer;
+class SkImage;
 
 class SK_API SkLights  : public SkRefCnt {
 public:
@@ -20,7 +23,8 @@
     public:
         enum LightType {
             kAmbient_LightType,       // only 'fColor' is used
-            kDirectional_LightType
+            kDirectional_LightType,
+            kPoint_LightType
         };
 
         Light(const Light& other)
@@ -37,26 +41,31 @@
             , fShadowMap(std::move(other.fShadowMap)) {
         }
 
-        Light(const SkColor3f& color)
-            : fType(kAmbient_LightType)
-            , fColor(color) {
-            fDirection.set(0.0f, 0.0f, 1.0f);
+        static Light MakeAmbient(const SkColor3f& color) {
+            return Light(kAmbient_LightType, color, SkVector3::Make(0.0f, 0.0f, 1.0f));
         }
 
-        Light(const SkColor3f& color, const SkVector3& dir)
-            : fType(kDirectional_LightType)
-            , fColor(color)
-            , fDirection(dir) {
-            if (!fDirection.normalize()) {
-                fDirection.set(0.0f, 0.0f, 1.0f);
+        static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir) {
+            Light light(kDirectional_LightType, color, dir);
+            if (!light.fDirection.normalize()) {
+                light.fDirection.set(0.0f, 0.0f, 1.0f);
             }
+            return light;
+        }
+
+        static Light MakePoint(const SkColor3f& color, const SkPoint3& pos) {
+            return Light(kPoint_LightType, color, pos);
         }
 
         LightType type() const { return fType; }
         const SkColor3f& color() const { return fColor; }
-        const SkVector3& dir() const { 
-            SkASSERT(kAmbient_LightType != fType);
-            return fDirection; 
+        const SkVector3& dir() const {
+            SkASSERT(kDirectional_LightType == fType);
+            return fDirection;
+        }
+        const SkPoint3& pos() const {
+            SkASSERT(kPoint_LightType == fType);
+            return fDirection;
         }
 
         void setShadowMap(sk_sp<SkImage> shadowMap) {
@@ -78,19 +87,26 @@
             fShadowMap = b.fShadowMap;
             return *this;
         }
-
     private:
         LightType   fType;
         SkColor3f   fColor;           // linear (unpremul) color. Range is 0..1 in each channel.
-        SkVector3   fDirection;       // direction towards the light (+Z is out of the screen).
+        SkVector3   fDirection;       // For directional lights, holds the direction towards the
+                                      // light (+Z is out of the screen).
                                       // If degenerate, it will be replaced with (0, 0, 1).
+                                      // For point lights, holds location of point light
         sk_sp<SkImage> fShadowMap;
+
+        Light(LightType type, const SkColor3f& color, const SkVector3& dir) {
+            fType = type;
+            fColor = color;
+            fDirection = dir;
+        }
     };
 
     class Builder {
     public:
         Builder() : fLights(new SkLights) { }
-    
+
         void add(const Light& light) {
             if (fLights) {
                 fLights->fLights.push_back(light);
@@ -123,11 +139,13 @@
         return fLights[index];
     }
 
+    static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
+
+    void flatten(SkWriteBuffer& buf) const;
+
 private:
     SkLights() {}
-
     SkTArray<Light> fLights;
-
     typedef SkRefCnt INHERITED;
 };
 
diff --git a/samplecode/SampleLighting.cpp b/samplecode/SampleLighting.cpp
index 1c86c99..bab2b5d 100755
--- a/samplecode/SampleLighting.cpp
+++ b/samplecode/SampleLighting.cpp
@@ -21,8 +21,8 @@
 
     SkLights::Builder builder;
 
-    builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, blue), dir));
-    builder.add(SkLights::Light(SkColor3f::Make(0.1f, 0.1f, 0.1f)));
+    builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, blue), dir));
+    builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.1f, 0.1f, 0.1f)));
 
     return builder.finish();
 }
diff --git a/samplecode/SampleLitAtlas.cpp b/samplecode/SampleLitAtlas.cpp
index 5f62e2a..cb49bf3 100644
--- a/samplecode/SampleLitAtlas.cpp
+++ b/samplecode/SampleLitAtlas.cpp
@@ -182,8 +182,9 @@
     void updateLights() {        
         SkLights::Builder builder;
 
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f), fLightDir));
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+        builder.add(SkLights::Light::MakeDirectional(
+                SkColor3f::Make(1.0f, 1.0f, 1.0f), fLightDir));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
 
         fLights = builder.finish();
     }
diff --git a/samplecode/SampleShadowing.cpp b/samplecode/SampleShadowing.cpp
index 7b434bc..d0b37fb 100644
--- a/samplecode/SampleShadowing.cpp
+++ b/samplecode/SampleShadowing.cpp
@@ -19,11 +19,11 @@
 
         this->setBGColor(0xFFCCCCCC);
         SkLights::Builder builder;
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f),
-                                    SkVector3::Make(0.2f, 0.05f, 1.0f)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f),
-                                    SkVector3::Make(0.05f, 0.2f, 1.0f)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.2f, 0.3f, 0.4f),
+                                                     SkVector3::Make(0.2f, 0.05f, 1.0f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.4f, 0.3f, 0.2f),
+                                                     SkVector3::Make(0.05f, 0.2f, 1.0f)));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
         fLights = builder.finish();
 
         fTestRects[0].fColor = 0xFFEE8888;
@@ -139,15 +139,18 @@
                 float recipY = 1.0f / kHeight;
 
                 SkLights::Builder builder;
-                builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.3f, 0.4f),
-                                            SkVector3::Make(0.2f + (200.0f - x) * recipX,
-                                                            0.05f + (200.0f - y) * recipY,
-                                                            1.0f)));
-                builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.3f, 0.2f),
-                                            SkVector3::Make(0.05f + (200.0f - x) * recipX,
-                                                            0.2f + (200.0f - y) * recipY,
-                                                            1.0f)));
-                builder.add(SkLights::Light(SkColor3f::Make(0.4f, 0.4f, 0.4f)));
+                builder.add(SkLights::Light::MakeDirectional(
+                        SkColor3f::Make(0.2f, 0.3f, 0.4f),
+                        SkVector3::Make(0.2f + (200.0f - x) * recipX,
+                                        0.05f + (200.0f - y) * recipY,
+                                        1.0f)));
+                builder.add(SkLights::Light::MakeDirectional(
+                        SkColor3f::Make(0.4f, 0.3f, 0.2f),
+                        SkVector3::Make(0.05f + (200.0f - x) * recipX,
+                                        0.2f + (200.0f - y) * recipY,
+                                        1.0f)));
+                builder.add(SkLights::Light::MakeAmbient(
+                        SkColor3f::Make(0.4f, 0.4f, 0.4f)));
                 fLights = builder.finish();
 
                 fLightsChanged = true;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 4160df7..d199e5d 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -3198,8 +3198,8 @@
     // povDepthMap
     {
         SkLights::Builder builder;
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
-                                    SkVector3::Make(0.0f, 0.0f, 1.0f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
+                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
         sk_sp<SkLights> povLight = builder.finish();
 
         SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index e8280b1..6f3c233 100644
--- a/src/core/SkLightingShader.cpp
+++ b/src/core/SkLightingShader.cpp
@@ -416,30 +416,7 @@
     bool hasLocalMatrix = buf.readBool();
     SkAssertResult(!hasLocalMatrix);
 
-    int numLights = buf.readInt();
-
-    SkLights::Builder builder;
-
-    for (int l = 0; l < numLights; ++l) {
-        bool isAmbient = buf.readBool();
-
-        SkColor3f color;
-        if (!buf.readScalarArray(&color.fX, 3)) {
-            return nullptr;
-        }
-
-        if (isAmbient) {
-            builder.add(SkLights::Light(color));
-        } else {
-            SkVector3 dir;
-            if (!buf.readScalarArray(&dir.fX, 3)) {
-                return nullptr;
-            }
-            builder.add(SkLights::Light(color, dir));
-        }
-    }
-
-    sk_sp<SkLights> lights(builder.finish());
+    sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf);
 
     sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>());
 
@@ -456,18 +433,7 @@
 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const {
     this->INHERITED::flatten(buf);
 
-    buf.writeInt(fLights->numLights());
-    for (int l = 0; l < fLights->numLights(); ++l) {
-        const SkLights::Light& light = fLights->light(l);
-
-        bool isAmbient = SkLights::Light::kAmbient_LightType == light.type();
-
-        buf.writeBool(isAmbient);
-        buf.writeScalarArray(&light.color().fX, 3);
-        if (!isAmbient) {
-            buf.writeScalarArray(&light.dir().fX, 3);
-        }
-    }
+    fLights->flatten(buf);
 
     buf.writeFlattenable(fNormalSource.get());
     buf.writeBool(fDiffuseShader);
diff --git a/src/core/SkLights.cpp b/src/core/SkLights.cpp
new file mode 100644
index 0000000..a172de4
--- /dev/null
+++ b/src/core/SkLights.cpp
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkLights.h"
+#include "SkReadBuffer.h"
+
+sk_sp<SkLights> SkLights::MakeFromBuffer(SkReadBuffer& buf) {
+    int numLights = buf.readInt();
+
+    Builder builder;
+    for (int l = 0; l < numLights; ++l) {
+        bool isAmbient = buf.readBool();
+        bool isPoint = buf.readBool();
+
+        SkColor3f color;
+        if (!buf.readScalarArray(&color.fX, 3)) {
+            return nullptr;
+        }
+
+        if (isAmbient) {
+            builder.add(Light::MakeAmbient(color));
+        } else {
+            SkVector3 dirOrPos;
+            if (!buf.readScalarArray(&dirOrPos.fX, 3)) {
+                return nullptr;
+            }
+
+            sk_sp<SkImage> depthMap;
+            bool hasShadowMap = buf.readBool();
+            if (hasShadowMap) {
+                if (!(depthMap = buf.readImage())) {
+                    return nullptr;
+                }
+            }
+
+            if (isPoint) {
+                Light light = Light::MakePoint(color, dirOrPos);
+                light.setShadowMap(depthMap);
+                builder.add(light);
+            } else {
+                Light light = Light::MakeDirectional(color, dirOrPos);
+                light.setShadowMap(depthMap);
+                builder.add(light);
+            }
+        }
+    }
+
+    return builder.finish();
+}
+
+void SkLights::flatten(SkWriteBuffer& buf) const {
+
+    buf.writeInt(this->numLights());
+    for (int l = 0; l < this->numLights(); ++l) {
+        const Light& light = this->light(l);
+
+        bool isAmbient = Light::kAmbient_LightType == light.type();
+        bool isPoint = Light::kPoint_LightType == light.type();
+
+        buf.writeBool(isAmbient);
+        buf.writeBool(isPoint);
+        buf.writeScalarArray(&light.color().fX, 3);
+        if (!isAmbient) {
+            buf.writeScalarArray(&light.dir().fX, 3);
+            bool hasShadowMap = light.getShadowMap() != nullptr;
+            buf.writeBool(hasShadowMap);
+            if (hasShadowMap) {
+                buf.writeImage(light.getShadowMap());
+            }
+        }
+    }
+}
diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp
index 5fc992a..8042583 100644
--- a/src/core/SkShadowShader.cpp
+++ b/src/core/SkShadowShader.cpp
@@ -592,39 +592,7 @@
     bool hasLocalMatrix = buf.readBool();
     SkAssertResult(!hasLocalMatrix);
 
-    int numLights = buf.readInt();
-
-    SkLights::Builder builder;
-
-    for (int l = 0; l < numLights; ++l) {
-        bool isAmbient = buf.readBool();
-
-        SkColor3f color;
-        if (!buf.readScalarArray(&color.fX, 3)) {
-            return nullptr;
-        }
-
-        if (isAmbient) {
-            builder.add(SkLights::Light(color));
-        } else {
-            SkVector3 dir;
-            if (!buf.readScalarArray(&dir.fX, 3)) {
-                return nullptr;
-            }
-
-            sk_sp<SkImage> depthMap;
-            if (!(depthMap = sk_ref_sp<SkImage>(buf.readImage()))) {
-                return nullptr;
-            }
-
-            SkLights::Light light = SkLights::Light(color, dir);
-            light.setShadowMap(depthMap);
-
-            builder.add(light);
-        }
-    }
-
-    sk_sp<SkLights> lights(builder.finish());
+    sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf);
 
     int diffuseWidth = buf.readInt();
     int diffuseHeight = buf.readInt();
@@ -641,21 +609,7 @@
 void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const {
     this->INHERITED::flatten(buf);
 
-    buf.writeInt(fLights->numLights());
-
-    for (int l = 0; l < fLights->numLights(); ++l) {
-        const SkLights::Light& light = fLights->light(l);
-
-        bool isAmbient = SkLights::Light::kAmbient_LightType == light.type();
-
-        buf.writeBool(isAmbient);
-        buf.writeScalarArray(&light.color().fX, 3);
-        if (!isAmbient) {
-            buf.writeScalarArray(&light.dir().fX, 3);
-        }
-
-        buf.writeImage(light.getShadowMap());
-    }
+    fLights->flatten(buf);
 
     buf.writeInt(fDiffuseWidth);
     buf.writeInt(fDiffuseHeight);
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index 86591b5..11a705f 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -556,9 +556,9 @@
 
         SkLights::Builder builder;
 
-        builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
-                                    SkVector3::Make(1.0f, 0.0f, 0.0f)));
-        builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
+                                                     SkVector3::Make(1.0f, 0.0f, 0.0f)));
+        builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
 
         sk_sp<SkLights> fLights = builder.finish();