1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SbColor4f SbColor4f.h Inventor/SbColor4f.h
35   \brief The SbColor4f class contains the red, green, blue and alpha
36   components which make up a color value.
37 
38   \ingroup base
39 
40   This class is used internally within other classes in Coin.  It contains
41   a 4 component vector as a position in the RGB cube with an additional
42   transparency value.
43 
44   The red, green and blue values should be between 0.0 and 1.0, where
45   0.0 is interpreted as minimum intensity, and 1.0 is maximum intensity.
46   The transparency value is also between 0.0 and 1.0.
47 
48   SbColor4f contains methods for convenient handling of setting and
49   getting color values as 32 bit packed values or as HSV values.
50 
51   Note: this class is not part of Open Inventor, but is an extension to
52   the API. Don't use it if you want your code to be compatible with
53   Open Inventor.
54 
55   \sa SbColor
56 */
57 
58 #include <cassert>
59 #include <Inventor/SbColor4f.h>
60 #include <Inventor/SbVec4f.h>
61 #if COIN_DEBUG
62 #include <Inventor/errors/SoDebugError.h>
63 #endif // COIN_DEBUG
64 
65 /*!
66   Default constructor. The color value will be uninitialized until
67   explicitly set.
68  */
SbColor4f(void)69 SbColor4f::SbColor4f(void)
70 {
71 }
72 
73 /*!
74   Construct and initialize an SbColor4f with the red, green, blue
75   and alpha values given by the \c v vector.
76  */
SbColor4f(const SbVec4f & v)77 SbColor4f::SbColor4f(const SbVec4f& v)
78 {
79   this->vec[0] = v[0];
80   this->vec[1] = v[1];
81   this->vec[2] = v[2];
82   this->vec[3] = v[3];
83 }
84 
85 /*!
86   Construct and initialize an SbColor4f with the red, green, blue
87   and alpha taken from given \c rgba array
88  */
SbColor4f(const float * const rgba)89 SbColor4f::SbColor4f(const float* const rgba)
90 {
91   this->vec[0] = rgba[0];
92   this->vec[1] = rgba[1];
93   this->vec[2] = rgba[2];
94   this->vec[3] = rgba[3];
95 }
96 
97 /*!
98   Construct and initialize an SbColor4f with the red, green and blue
99   components from the SbColor \c rgb, and the alpha value from the
100   supplied \c alpha argument.
101 */
SbColor4f(const SbColor & rgb,const float alpha)102 SbColor4f::SbColor4f(const SbColor &rgb, const float alpha)
103 {
104   this->vec[0] = rgb[0];
105   this->vec[1] = rgb[1];
106   this->vec[2] = rgb[2];
107   this->vec[3] = alpha;
108 }
109 
110 /*!
111   Construct and initialize an SbColor4f with the given red, green, blue
112   and alpha values.
113  */
SbColor4f(const float r,const float g,const float b,const float a)114 SbColor4f::SbColor4f(const float r, const float g, const float b,
115                    const float a)
116 {
117   this->vec[0] = r;
118   this->vec[1] = g;
119   this->vec[2] = b;
120   this->vec[3] = a;
121 }
122 
123 
124 /*!
125   Set a new color.
126  */
127 void
setValue(const float r,const float g,const float b,const float a)128 SbColor4f::setValue(const float r, const float g, const float b,
129                    const float a)
130 {
131   this->vec[0] = r;
132   this->vec[1] = g;
133   this->vec[2] = b;
134   this->vec[3] = a;
135 }
136 
137 /*!
138   Set a new color. The elements of the array will be read in turned
139   as red, green, blue and transparency.
140  */
141 void
setValue(const float col[4])142 SbColor4f::setValue(const float col[4])
143 {
144   this->vec[0] = col[0];
145   this->vec[1] = col[1];
146   this->vec[2] = col[2];
147   this->vec[3] = col[3];
148 }
149 
150 /*!
151   Return pointer to array of 4 float values representing the red, green,
152   blue and transparency values of the color.
153  */
154 const float *
getValue() const155 SbColor4f::getValue() const
156 {
157   return this->vec;
158 }
159 
160 /*!
161   Return components of the stored color.
162  */
163 void
getValue(float & r,float & g,float & b,float & a)164 SbColor4f::getValue(float &r, float &g, float &b, float &a)
165 {
166   r = this->vec[0];
167   g = this->vec[1];
168   b = this->vec[2];
169   a = this->vec[3];
170 }
171 
172 
173 /*!
174   Set the color value as a 32 bit combined red/green/blue/alpha value.
175   Each component is 8 bit wide (i.e. from 0x00 to 0xff), and the red
176   value should be stored leftmost, like this: 0xRRGGBBAA.
177 
178   \sa getPackedValue().
179  */
180 SbColor4f&
setPackedValue(const uint32_t rgba)181 SbColor4f::setPackedValue(const uint32_t rgba)
182 {
183   this->setValue((rgba >> 24)/255.0f,
184                  ((rgba >> 16)&0xff)/255.0f,
185                  ((rgba >> 8)&0xff)/255.0f,
186                  (rgba & 0xff)/255.0f);
187   return *this;
188 }
189 
190 /*!
191   Return color as a 32 bit packed integer in the form 0xRRGGBBAA.
192   \sa setPackedValue().
193  */
194 uint32_t
getPackedValue() const195 SbColor4f::getPackedValue() const
196 {
197   return ((static_cast<uint32_t>(red()*255.0f + 0.5f) << 24) |
198           (static_cast<uint32_t>(green()*255.0f + 0.5f) << 16) |
199           (static_cast<uint32_t>(blue()*255.0f + 0.5f) << 8) |
200           static_cast<uint32_t>(alpha()*255.0f + 0.5f));
201 }
202 
203 /*!
204   Sets the RGB components of the color. The alpha component is
205   left unchanged.
206 */
207 SbColor4f&
setRGB(const SbColor & col)208 SbColor4f::setRGB(const SbColor &col)
209 {
210   this->vec[0] = col[0];
211   this->vec[1] = col[1];
212   this->vec[2] = col[2];
213   return *this;
214 }
215 
216 /*!
217   Returns the RGB components of this color.
218 */
219 void
getRGB(SbColor & color)220 SbColor4f::getRGB(SbColor &color)
221 {
222   color[0] = this->red();
223   color[1] = this->green();
224   color[2] = this->blue();
225 }
226 
227 /*!
228   Set the color as a \c hue, \c saturation, \c value triplet.
229   The hue component should be normalized to within [0, 1] before you
230   call this method, where 0 is equal to 0� and 1 is equal to 360�.
231 
232   \sa getHSVValue().
233  */
234 SbColor4f&
setHSVValue(float hue,float saturation,float value,float alpha)235 SbColor4f::setHSVValue(float hue, float saturation,
236                       float value, float alpha)
237 {
238 #if COIN_DEBUG
239   if (!(hue>=0.0f && hue<=1.0f)) {
240     SoDebugError::postWarning("SbColor4f::setHSVValue",
241                               "'hue' (%f) not within [0.0,1.0]; clamping.",
242                               hue);
243     if (hue<0.0f) hue=0.0f;
244     else if (hue>1.0f) hue=1.0f;
245   }
246 
247   if (!(saturation>=0.0f && saturation<=1.0f)) {
248     SoDebugError::postWarning("SbColor4f::setHSVValue",
249                               "'saturation' (%f) not within [0.0,1.0]; "
250                               "clamping.", saturation);
251     if (saturation<0.0f) saturation=0.0f;
252     else if (saturation>1.0f) saturation=1.0f;
253   }
254 
255   if (!(value>=0.0f && value<=1.0f)) {
256     SoDebugError::postWarning("SbColor4f::setHSVValue",
257                               "'value' (%f) not within [0.0,1.0]; clamping.",
258                               value);
259     if (value<0.0f) value=0.0f;
260     else if (value>1.0f) value=1.0f;
261   }
262   if (!(alpha >= 0.0f && alpha <= 1.0f)) {
263     SoDebugError::postWarning("SbColor4f::setHSVValue",
264                               "'alpha' (%f) not within [0.0,1.0]; clamping.",
265                               alpha);
266     alpha = SbClamp(alpha, 0.0f, 1.0f);
267   }
268 
269 #endif // COIN_DEBUG
270 
271   SbColor col;
272   col.setHSVValue(hue, saturation, value);
273   this->vec[0] = col[0];
274   this->vec[1] = col[1];
275   this->vec[2] = col[2];
276   this->vec[3] = alpha;
277   return *this;
278 }
279 
280 /*!
281   Return the color as a \c hue, \c saturation, \c value triplet. Alpha
282   component is ignored.
283 
284   \sa setHSVValue().
285  */
286 void
getHSVValue(float & h,float & s,float & v) const287 SbColor4f::getHSVValue(float &h, float &s, float &v) const
288 {
289   SbColor col;
290   col[0] = this->vec[0];
291   col[1] = this->vec[1];
292   col[2] = this->vec[2];
293   col.getHSVValue(h, s, v);
294 }
295 
296 /*!
297   Set the color as a \c hue, \c saturation, \c value triplet.
298   The hue component should be normalized to within [0, 1] before you
299   call this method, where 0 is equal to 0� and 1 is equal to 360�.
300 
301   \sa getHSVValue().
302  */
303 SbColor4f&
setHSVValue(const float hsv[3],float a)304 SbColor4f::setHSVValue(const float hsv[3], float a)
305 {
306   return this->setHSVValue(hsv[0], hsv[1], hsv[2], a);
307 }
308 
309 /*!
310   Return the color as a \c hue, \c saturation, \c value triplet. Alpha
311   component is ignored.
312 
313   \sa setHSVValue().
314  */
315 void
getHSVValue(float hsv[3]) const316 SbColor4f::getHSVValue(float hsv[3]) const
317 {
318   this->getHSVValue(hsv[0], hsv[1], hsv[2]);
319 }
320 
321 /*!
322   Returns the color component represented by the given index \a idx.
323   0 is red, 1 is green, 2 is blue and 3 is the transparency value.
324  */
325 //$ EXPORT INLINE
326 float
operator [](const int idx) const327 SbColor4f::operator[](const int idx) const
328 {
329   return this->vec[idx];
330 }
331 
332 /*!
333   Returns the color component represented by the given index \a idx.
334   0 is red, 1 is green, 2 is blue and 3 is the transparency value.
335  */
336 //$ EXPORT INLINE
337 float &
operator [](const int idx)338 SbColor4f::operator[](const int idx)
339 {
340   return this->vec[idx];
341 }
342 
343 /*!
344   Multiplies the RGB components by \c d. The alpha component is left
345   unchanged.
346 */
347 SbColor4f &
operator *=(const float d)348 SbColor4f::operator*=(const float d)
349 {
350   this->vec[0] *= d;
351   this->vec[1] *= d;
352   this->vec[2] *= d;
353   return *this;
354 }
355 
356 /*!
357   Divides the RGB components by \c d. The alpha component is left
358   unchanged.
359 */
360 SbColor4f &
operator /=(const float d)361 SbColor4f::operator/=(const float d)
362 {
363   this->vec[0] /= d;
364   this->vec[1] /= d;
365   this->vec[2] /= d;
366   return *this;
367 }
368 
369 /*!
370   Adds the RGB components. Alpha is ignored.
371 */
372 SbColor4f &
operator +=(const SbColor4f & c)373 SbColor4f::operator+=(const SbColor4f &c)
374 {
375   this->vec[0] += c[0];
376   this->vec[1] += c[1];
377   this->vec[2] += c[2];
378   return *this;
379 }
380 
381 /*!
382   Subtracts the RGB components. Alpha is ignored.
383 */
384 SbColor4f &
operator -=(const SbColor4f & c)385 SbColor4f::operator-=(const SbColor4f &c)
386 {
387   this->vec[0] -= c[0];
388   this->vec[1] -= c[1];
389   this->vec[2] -= c[2];
390   return *this;
391 }
392 
393 /*!
394   Multiplies the RGB components by \c d. Alpha is left unchanged.
395 */
396 SbColor4f
operator *(const SbColor4f & c,const float d)397 operator *(const SbColor4f &c, const float d)
398 {
399   return SbColor4f(c.vec[0]*d, c.vec[1]*d, c.vec[2]*d, c.vec[3]);
400 }
401 
402 /*!
403   Multiplies the RGB components by \c d. Alpha is left unchanged.
404 */
405 SbColor4f
operator *(const float d,const SbColor4f & c)406 operator *(const float d, const SbColor4f &c)
407 {
408   return SbColor4f(c.vec[0]*d, c.vec[1]*d, c.vec[2]*d, c.vec[3]);
409 }
410 
411 /*!
412   Divides the RGB components by \c d. Alpha is left unchanged.
413 */
414 SbColor4f
operator /(const SbColor4f & c,const float d)415 operator /(const SbColor4f &c, const float d)
416 {
417   assert(d != 0.0f);
418   float inv = 1.0f / d;
419   return SbColor4f(c.vec[0]*inv,
420                   c.vec[1]*inv,
421                   c.vec[2]*inv,
422                   c.vec[3]);
423 }
424 
425 /*!
426   Adds the RGB components of the two colors. Alpha is taken from the
427   first color (\c v1).
428 */
429 SbColor4f
operator +(const SbColor4f & v1,const SbColor4f & v2)430 operator +(const SbColor4f &v1, const SbColor4f &v2)
431 {
432   return SbColor4f(v1.vec[0] + v2.vec[0],
433                   v1.vec[1] + v2.vec[1],
434                   v1.vec[2] + v2.vec[2],
435                   v1.vec[3]);
436 }
437 
438 /*!
439   Subtracts the RGB components of the two colors. Alpha is taken from the
440   first color (\c v1).
441 */
442 SbColor4f
operator -(const SbColor4f & v1,const SbColor4f & v2)443 operator -(const SbColor4f &v1, const SbColor4f &v2)
444 {
445   return SbColor4f(v1.vec[0] - v2.vec[0],
446                   v1.vec[1] - v2.vec[1],
447                   v1.vec[2] - v2.vec[2],
448                   v1.vec[3]);
449 }
450 
451 /*!
452   Check if two colors are equal. Returns 1 if equal, 0 if unequal.
453  */
454 int
operator ==(const SbColor4f & v1,const SbColor4f & v2)455 operator ==(const SbColor4f &v1, const SbColor4f &v2)
456 {
457   return (v1.vec[0] == v2.vec[0] &&
458           v1.vec[1] == v2.vec[1] &&
459           v1.vec[2] == v2.vec[2] &&
460           v1.vec[3] == v2.vec[3]);
461 }
462 
463 /*!
464   Check if two colors are unequal. Returns 0 if equal, 1 if unequal.
465  */
466 //$ EXPORT INLINE
467 int
operator !=(const SbColor4f & v1,const SbColor4f & v2)468 operator !=(const SbColor4f &v1, const SbColor4f &v2)
469 {
470   return !(v1 == v2);
471 }
472