|  |  | 
|  | /* | 
|  | * 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 "include/core/SkPoint3.h" | 
|  | #include "include/core/SkRefCnt.h" | 
|  | #include "include/private/SkTArray.h" | 
|  |  | 
|  | class SkReadBuffer; | 
|  | class SkWriteBuffer; | 
|  |  | 
|  | /** \class SkLights | 
|  | SkLights encapsulates a set of directional, point and ambient lights for use with the | 
|  | SkLightingShader. | 
|  | */ | 
|  | 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) {} | 
|  |  | 
|  | Light(Light&& other) | 
|  | : fType(other.fType) | 
|  | , fColor(other.fColor) | 
|  | , fDirOrPos(other.fDirOrPos) | 
|  | , fIntensity(other.fIntensity) {} | 
|  |  | 
|  | static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir) { | 
|  | Light light(kDirectional_LightType, color, dir, 0.0f); | 
|  | 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) { | 
|  | return Light(kPoint_LightType, color, pos, intensity); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | Light& operator=(const Light& other) { | 
|  | if (this == &other) { | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | fType = other.fType; | 
|  | fColor = other.fColor; | 
|  | fDirOrPos = other.fDirOrPos; | 
|  | fIntensity = other.fIntensity; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | bool operator==(const Light& other) { | 
|  | return (fType      == other.fType) && | 
|  | (fColor     == other.fColor) && | 
|  | (fDirOrPos  == other.fDirOrPos) && | 
|  | (fIntensity == other.fIntensity); | 
|  | } | 
|  |  | 
|  | bool operator!=(const Light& other) { return !(this->operator==(other)); } | 
|  |  | 
|  | private: | 
|  | friend class SkLights; | 
|  |  | 
|  | Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos, | 
|  | SkScalar intensity) | 
|  | : fType(type) | 
|  | , fColor(color) | 
|  | , fDirOrPos(dirOrPos) | 
|  | , fIntensity(intensity) {} | 
|  |  | 
|  | 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. | 
|  | }; | 
|  |  | 
|  | 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; | 
|  | }; | 
|  |  | 
|  | /** Returns number of lights not including the ambient light. | 
|  |  | 
|  | @return number of lights not including the ambient light | 
|  | */ | 
|  | int numLights() const { return fLights.count(); } | 
|  |  | 
|  | /** Returns the index-th light. | 
|  |  | 
|  | @param index  the index of the desired light | 
|  | @return       the index-th light | 
|  | */ | 
|  | const Light& light(int index) const { return fLights[index]; } | 
|  |  | 
|  | /** Returns the ambient light. | 
|  |  | 
|  | @return the ambient light | 
|  | */ | 
|  | const SkColor3f& ambientLightColor() const { | 
|  | return fAmbientLightColor; | 
|  | } | 
|  |  | 
|  | /** | 
|  | *  Recreate an SkLights object that was serialized into a buffer. | 
|  | * | 
|  | *  @param  SkReadBuffer Serialized blob data. | 
|  | *  @return A new SkLights representing the serialized data, or NULL if the buffer is | 
|  | *          invalid. | 
|  | */ | 
|  | static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf); | 
|  |  | 
|  | /** | 
|  | *  Serialize to a buffer. | 
|  | * | 
|  | *  @param  buffer the write buffer to write out to | 
|  | */ | 
|  | void flatten(SkWriteBuffer& buf) const; | 
|  |  | 
|  | private: | 
|  | friend class SkLightingShaderImpl; | 
|  |  | 
|  | SkLights() : fAmbientLightColor(SkColor3f::Make(0.0f, 0.0f, 0.0f)) {} | 
|  |  | 
|  | SkTArray<Light> fLights; | 
|  | SkColor3f       fAmbientLightColor; | 
|  |  | 
|  | typedef SkRefCnt INHERITED; | 
|  | }; | 
|  |  | 
|  | #endif |