|  | 
 | /* | 
 |  * Copyright 2015 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #ifndef SkLights_DEFINED | 
 | #define SkLights_DEFINED | 
 |  | 
 | #include "../private/SkTArray.h" | 
 | #include "SkPoint3.h" | 
 | #include "SkRefCnt.h" | 
 |  | 
 | class SkReadBuffer; | 
 | class SkWriteBuffer; | 
 | class SkImage; | 
 |  | 
 | class SK_API SkLights  : public SkRefCnt { | 
 | public: | 
 |     class Light { | 
 |     public: | 
 |         enum LightType { | 
 |             kDirectional_LightType, | 
 |             kPoint_LightType | 
 |         }; | 
 |  | 
 |         Light(const Light& other) | 
 |             : fType(other.fType) | 
 |             , fColor(other.fColor) | 
 |             , fDirOrPos(other.fDirOrPos) | 
 |             , fIntensity(other.fIntensity) | 
 |             , fShadowMap(other.fShadowMap) | 
 |             , fIsRadial(other.fIsRadial) { | 
 |         } | 
 |  | 
 |         Light(Light&& other) | 
 |             : fType(other.fType) | 
 |             , fColor(other.fColor) | 
 |             , fDirOrPos(other.fDirOrPos) | 
 |             , fIntensity(other.fIntensity) | 
 |             , fShadowMap(std::move(other.fShadowMap)) | 
 |             , fIsRadial(other.fIsRadial)  { | 
 |         } | 
 |  | 
 |         static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir, | 
 |                                      bool isRadial = false) { | 
 |             Light light(kDirectional_LightType, color, dir, isRadial); | 
 |             if (!light.fDirOrPos.normalize()) { | 
 |                 light.fDirOrPos.set(0.0f, 0.0f, 1.0f); | 
 |             } | 
 |             return light; | 
 |         } | 
 |  | 
 |         static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity, | 
 |                                bool isRadial = false) { | 
 |             return Light(kPoint_LightType, color, pos, intensity, isRadial); | 
 |         } | 
 |  | 
 |         LightType type() const { return fType; } | 
 |         const SkColor3f& color() const { return fColor; } | 
 |         const SkVector3& dir() const { | 
 |             SkASSERT(kDirectional_LightType == fType); | 
 |             return fDirOrPos; | 
 |         } | 
 |         const SkPoint3& pos() const { | 
 |             SkASSERT(kPoint_LightType == fType); | 
 |             return fDirOrPos; | 
 |         } | 
 |         SkScalar intensity() const { | 
 |             SkASSERT(kPoint_LightType == fType); | 
 |             return fIntensity; | 
 |         } | 
 |  | 
 |         void setShadowMap(sk_sp<SkImage> shadowMap) { | 
 |             fShadowMap = std::move(shadowMap); | 
 |         } | 
 |  | 
 |         SkImage* getShadowMap() const { | 
 |             return fShadowMap.get(); | 
 |         } | 
 |  | 
 |         bool isRadial() const { return fIsRadial; } | 
 |  | 
 |         Light& operator= (const Light& b) { | 
 |             if (this == &b) { | 
 |                 return *this; | 
 |             } | 
 |  | 
 |             fColor = b.fColor; | 
 |             fType = b.fType; | 
 |             fDirOrPos = b.fDirOrPos; | 
 |             fIntensity = b.fIntensity; | 
 |             fShadowMap = b.fShadowMap; | 
 |             fIsRadial = b.fIsRadial; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         bool operator== (const Light& b) { | 
 |             if (this == &b) { | 
 |                 return true; | 
 |             } | 
 |  | 
 |             return (fColor     == b.fColor) && | 
 |                    (fType      == b.fType) && | 
 |                    (fDirOrPos  == b.fDirOrPos) && | 
 |                    (fShadowMap == b.fShadowMap) && | 
 |                    (fIntensity == b.fIntensity) && | 
 |                    (fIsRadial  == b.fIsRadial); | 
 |         } | 
 |  | 
 |         bool operator!= (const Light& b) { return !(this->operator==(b)); } | 
 |  | 
 |     private: | 
 |         LightType   fType; | 
 |         SkColor3f   fColor;           // linear (unpremul) color. Range is 0..1 in each channel. | 
 |  | 
 |         SkVector3   fDirOrPos;        // 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 | 
 |  | 
 |         SkScalar    fIntensity;       // For point lights, dictates the light intensity. | 
 |                                       // Simply a multiplier to the final light output value. | 
 |         sk_sp<SkImage> fShadowMap; | 
 |         bool        fIsRadial;        // Whether the light is radial or not. Radial lights will | 
 |                                       // cast shadows and lights radially outwards. | 
 |  | 
 |         Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos, | 
 |               SkScalar intensity = 0.0f, bool isRadial = false) { | 
 |             fType = type; | 
 |             fColor = color; | 
 |             fDirOrPos = dirOrPos; | 
 |             fIntensity = intensity; | 
 |             fIsRadial = isRadial; | 
 |         } | 
 |     }; | 
 |  | 
 |     class Builder { | 
 |     public: | 
 |         Builder() : fLights(new SkLights) {} | 
 |  | 
 |         void add(const Light& light) { | 
 |             if (fLights) { | 
 |                 fLights->fLights.push_back(light); | 
 |             } | 
 |         } | 
 |  | 
 |         void add(Light&& light) { | 
 |             if (fLights) { | 
 |                 fLights->fLights.push_back(std::move(light)); | 
 |             } | 
 |         } | 
 |  | 
 |         void setAmbientLightColor(const SkColor3f& color) { | 
 |             if (fLights) { | 
 |                 fLights->fAmbientLightColor = color; | 
 |             } | 
 |         } | 
 |  | 
 |         sk_sp<SkLights> finish() { | 
 |             return std::move(fLights); | 
 |         } | 
 |  | 
 |     private: | 
 |         sk_sp<SkLights> fLights; | 
 |     }; | 
 |  | 
 |     int numLights() const { | 
 |         return fLights.count(); | 
 |     } | 
 |  | 
 |     const Light& light(int index) const { | 
 |         return fLights[index]; | 
 |     } | 
 |  | 
 |     Light& light(int index) { | 
 |         return fLights[index]; | 
 |     } | 
 |  | 
 |     const SkColor3f& ambientLightColor() const { | 
 |         return fAmbientLightColor; | 
 |     } | 
 |  | 
 |     static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf); | 
 |  | 
 |     void flatten(SkWriteBuffer& buf) const; | 
 |  | 
 | private: | 
 |     SkLights() { | 
 |         fAmbientLightColor.set(0.0f, 0.0f, 0.0f); | 
 |     } | 
 |     SkTArray<Light> fLights; | 
 |     SkColor3f fAmbientLightColor; | 
 |     typedef SkRefCnt INHERITED; | 
 | }; | 
 |  | 
 | #endif |