blob: ee5aa44ab1297d5bd4b0f9240dd78024f03472ed [file] [log] [blame]
// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_RENDER_TREE_COLOR_RGBA_H_
#define COBALT_RENDER_TREE_COLOR_RGBA_H_
#include "base/logging.h"
namespace cobalt {
namespace render_tree {
// Note: this does not handle infinities or nans.
inline float clamp(float input, float min, float max) {
#if defined(STARBOARD)
if (SB_UNLIKELY(input < min)) return min;
if (SB_UNLIKELY(input > max)) return max;
#else
if (input < min) return min;
if (input > max) return max;
#endif
return input;
}
// Used to specify a color in the RGB (plus alpha) space.
// This color format is referenced by many render_tree objects in order to
// specify a color.
struct ColorRGBA {
public:
ColorRGBA() : r_(0), g_(0), b_(0), a_(0) {}
ColorRGBA(float red, float green, float blue) {
CheckRange(red);
r_ = red;
CheckRange(green);
g_ = green;
CheckRange(blue);
b_ = blue;
a_ = 1.0f;
}
ColorRGBA(float red, float green, float blue, float alpha) {
CheckRange(red);
r_ = red;
CheckRange(green);
g_ = green;
CheckRange(blue);
b_ = blue;
CheckRange(alpha);
a_ = alpha;
}
// Decodes the color value from 32-bit integer (4 channels, 8 bits each).
// Note that alpha channel is mandatory, so opaque colors should be encoded
// as 0xrrggbbff.
explicit ColorRGBA(uint32_t rgba) {
a_ = (rgba & 0xff) / 255.0f;
rgba >>= 8;
b_ = (rgba & 0xff) / 255.0f;
rgba >>= 8;
g_ = (rgba & 0xff) / 255.0f;
rgba >>= 8;
r_ = (rgba & 0xff) / 255.0f;
}
void set_r(float value) {
CheckRange(value);
r_ = value;
}
void set_g(float value) {
CheckRange(value);
g_ = value;
}
void set_b(float value) {
CheckRange(value);
b_ = value;
}
void set_a(float value) {
CheckRange(value);
a_ = value;
}
// These functions clamp the color channel values between 0.0f and 1.0f.
float r() const { return clamp(r_, 0.0f, 1.0f); }
float g() const { return clamp(g_, 0.0f, 1.0f); }
float b() const { return clamp(b_, 0.0f, 1.0f); }
float a() const { return clamp(a_, 0.0f, 1.0f); }
uint8_t rgb8_r() const { return static_cast<uint8_t>(r() * 255); }
uint8_t rgb8_g() const { return static_cast<uint8_t>(g() * 255); }
uint8_t rgb8_b() const { return static_cast<uint8_t>(b() * 255); }
uint8_t rgb8_a() const { return static_cast<uint8_t>(a() * 255); }
ColorRGBA& operator=(const ColorRGBA& other) {
r_ = other.r_;
g_ = other.g_;
b_ = other.b_;
a_ = other.a_;
return *this;
}
ColorRGBA& operator-=(const ColorRGBA& other) {
r_ -= other.r_;
g_ -= other.g_;
b_ -= other.b_;
a_ -= other.a_;
return *this;
}
ColorRGBA& operator+=(const ColorRGBA& other) {
r_ += other.r_;
g_ += other.g_;
b_ += other.b_;
a_ += other.a_;
return *this;
}
ColorRGBA& operator+=(const float f) {
r_ += f;
b_ += f;
g_ += f;
a_ += f;
return *this;
}
ColorRGBA& operator-=(const float f) {
r_ -= f;
b_ -= f;
g_ -= f;
a_ -= f;
return *this;
}
ColorRGBA& operator*=(const float f) {
r_ *= f;
b_ *= f;
g_ *= f;
a_ *= f;
return *this;
}
ColorRGBA& operator/=(const float f) {
float one_over_f(1.0f / f);
*this *= one_over_f;
return *this;
}
bool HasAlpha() const { return (a_ < 1.0f); }
private:
void CheckRange(float value) const {
DCHECK_LE(0.0f, value);
DCHECK_GE(1.0f, value);
}
float r_, g_, b_, a_;
};
inline bool operator==(const ColorRGBA& lhs, const ColorRGBA& rhs) {
return lhs.r() == rhs.r() && lhs.g() == rhs.g() && lhs.b() == rhs.b() &&
lhs.a() == rhs.a();
}
inline bool operator!=(const ColorRGBA& lhs, const ColorRGBA& rhs) {
return !(lhs == rhs);
}
inline ColorRGBA operator-(const ColorRGBA& lhs, const ColorRGBA& rhs) {
ColorRGBA color(lhs);
color -= rhs;
return color;
}
inline ColorRGBA operator+(const ColorRGBA& lhs, const ColorRGBA& rhs) {
ColorRGBA color(lhs);
color += rhs;
return color;
}
inline ColorRGBA operator+(const ColorRGBA& lhs, const float rhs) {
ColorRGBA color(lhs);
color += rhs;
return color;
}
inline ColorRGBA operator-(const ColorRGBA& lhs, const float rhs) {
ColorRGBA color(lhs);
color -= rhs;
return color;
}
inline ColorRGBA operator*(const ColorRGBA& lhs, const float rhs) {
ColorRGBA color(lhs);
color *= rhs;
return color;
}
inline ColorRGBA operator/(const ColorRGBA& lhs, const float rhs) {
ColorRGBA color(lhs);
color /= rhs;
return color;
}
// Used by tests.
inline std::ostream& operator<<(std::ostream& stream, const ColorRGBA& color) {
return stream << "rgba(" << color.r() << ", " << color.g() << ", "
<< color.b() << ", " << color.a() << ")";
}
} // namespace render_tree
} // namespace cobalt
#endif // COBALT_RENDER_TREE_COLOR_RGBA_H_