1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef sw_Color_hpp
16#define sw_Color_hpp
17
18#include "System/Types.hpp"
19#include "System/Math.hpp"
20
21namespace sw
22{
23 template<class T>
24 struct Color
25 {
26 Color();
27
28 Color(const Color<byte> &c);
29 Color(const Color<short> &c);
30 Color(const Color<float> &c);
31
32 Color(int c);
33 Color(unsigned short c);
34 Color(unsigned long c);
35 Color(unsigned int c);
36
37 Color(T r, T g, T b, T a = 1);
38
39 operator unsigned int() const;
40
41 T &operator[](int i);
42 const T &operator[](int i) const;
43
44 Color<T> operator+() const;
45 Color<T> operator-() const;
46
47 Color<T>& operator=(const Color<T>& c);
48
49 Color<T> &operator+=(const Color<T> &c);
50 Color<T> &operator*=(float l);
51
52 static Color<T> gradient(const Color<T> &c1, const Color<T> &c2, float d);
53 static Color<T> shade(const Color<T> &c1, const Color<T> &c2, float d);
54
55 template<class S>
56 friend Color<S> operator+(const Color<S> &c1, const Color<S> &c2);
57 template<class S>
58 friend Color<S> operator-(const Color<S> &c1, const Color<S> &c2);
59
60 template<class S>
61 friend Color<S> operator*(float l, const Color<S> &c);
62 template<class S>
63 friend Color<S> operator*(const Color<S> &c1, const Color<S> &c2);
64 template<class S>
65 friend Color<S> operator/(const Color<S> &c, float l);
66
67 T r;
68 T g;
69 T b;
70 T a;
71 };
72}
73
74#include "System/Math.hpp"
75
76namespace sw
77{
78 template<class T>
79 inline Color<T>::Color()
80 {
81 }
82
83 template<>
84 inline Color<byte>::Color(const Color<byte> &c)
85 {
86 r = c.r;
87 g = c.g;
88 b = c.b;
89 a = c.a;
90 }
91
92 template<>
93 inline Color<byte>::Color(const Color<short> &c)
94 {
95 r = static_cast<byte>(clamp(c.r >> 4, 0, 255));
96 g = static_cast<byte>(clamp(c.g >> 4, 0, 255));
97 b = static_cast<byte>(clamp(c.b >> 4, 0, 255));
98 a = static_cast<byte>(clamp(c.a >> 4, 0, 255));
99 }
100
101 template<>
102 inline Color<byte>::Color(const Color<float> &c)
103 {
104 r = static_cast<byte>(ifloor(clamp(c.r * 256.0f, 0.0f, 255.0f)));
105 g = static_cast<byte>(ifloor(clamp(c.g * 256.0f, 0.0f, 255.0f)));
106 b = static_cast<byte>(ifloor(clamp(c.b * 256.0f, 0.0f, 255.0f)));
107 a = static_cast<byte>(ifloor(clamp(c.a * 256.0f, 0.0f, 255.0f)));
108 }
109
110 template<>
111 inline Color<short>::Color(const Color<short> &c)
112 {
113 r = c.r;
114 g = c.g;
115 b = c.b;
116 a = c.a;
117 }
118
119 template<>
120 inline Color<short>::Color(const Color<byte> &c)
121 {
122 r = c.r << 4;
123 g = c.g << 4;
124 b = c.b << 4;
125 a = c.a << 4;
126 }
127
128 template<>
129 inline Color<float>::Color(const Color<float> &c)
130 {
131 r = c.r;
132 g = c.g;
133 b = c.b;
134 a = c.a;
135 }
136
137 template<>
138 inline Color<short>::Color(const Color<float> &c)
139 {
140 r = static_cast<short>(iround(clamp(c.r * 4095.0f, -4096.0f, 4095.0f)));
141 g = static_cast<short>(iround(clamp(c.g * 4095.0f, -4096.0f, 4095.0f)));
142 b = static_cast<short>(iround(clamp(c.b * 4095.0f, -4096.0f, 4095.0f)));
143 a = static_cast<short>(iround(clamp(c.a * 4095.0f, -4096.0f, 4095.0f)));
144 }
145
146 template<>
147 inline Color<float>::Color(const Color<byte> &c)
148 {
149 r = c.r / 255.0f;
150 g = c.g / 255.0f;
151 b = c.b / 255.0f;
152 a = c.a / 255.0f;
153 }
154
155 template<>
156 inline Color<float>::Color(const Color<short> &c)
157 {
158 r = c.r / 4095.0f;
159 g = c.g / 4095.0f;
160 b = c.b / 4095.0f;
161 a = c.a / 4095.0f;
162 }
163
164 template<>
165 inline Color<float>::Color(unsigned short c)
166 {
167 r = (float)(c & 0xF800) / (float)0xF800;
168 g = (float)(c & 0x07E0) / (float)0x07E0;
169 b = (float)(c & 0x001F) / (float)0x001F;
170 a = 1;
171 }
172
173 template<>
174 inline Color<short>::Color(unsigned short c)
175 {
176 // 4.12 fixed-point format
177 r = ((c & 0xF800) >> 4) + ((c & 0xF800) >> 9) + ((c & 0xF800) >> 14);
178 g = ((c & 0x07E0) << 1) + ((c & 0x07E0) >> 5);
179 b = ((c & 0x001F) << 7) + ((c & 0x001F) << 2) + ((c & 0x001F) >> 3);
180 a = 0x1000;
181 }
182
183 template<>
184 inline Color<byte>::Color(unsigned short c)
185 {
186 r = (byte)(((c & 0xF800) >> 8) + ((c & 0xE000) >> 13));
187 g = (byte)(((c & 0x07E0) >> 3) + ((c & 0x0600) >> 9));
188 b = (byte)(((c & 0x001F) << 3) + ((c & 0x001C) >> 2));
189 a = 0xFF;
190 }
191
192 template<>
193 inline Color<float>::Color(int c)
194 {
195 const float d = 1.0f / 255.0f;
196
197 r = (float)((c & 0x00FF0000) >> 16) * d;
198 g = (float)((c & 0x0000FF00) >> 8) * d;
199 b = (float)((c & 0x000000FF) >> 0) * d;
200 a = (float)((c & 0xFF000000) >> 24) * d;
201 }
202
203 template<>
204 inline Color<short>::Color(int c)
205 {
206 // 4.12 fixed-point format
207 r = (short)((c & 0x00FF0000) >> 12);
208 g = (short)((c & 0x0000FF00) >> 4);
209 b = (short)((c & 0x000000FF) << 4);
210 a = (short)((c & 0xFF000000) >> 20);
211 }
212
213 template<>
214 inline Color<byte>::Color(int c)
215 {
216 r = (byte)((c & 0x00FF0000) >> 16);
217 g = (byte)((c & 0x0000FF00) >> 8);
218 b = (byte)((c & 0x000000FF) >> 0);
219 a = (byte)((c & 0xFF000000) >> 24);
220 }
221
222 template<>
223 inline Color<float>::Color(unsigned int c)
224 {
225 const float d = 1.0f / 255.0f;
226
227 r = (float)((c & 0x00FF0000) >> 16) * d;
228 g = (float)((c & 0x0000FF00) >> 8) * d;
229 b = (float)((c & 0x000000FF) >> 0) * d;
230 a = (float)((c & 0xFF000000) >> 24) * d;
231 }
232
233 template<>
234 inline Color<short>::Color(unsigned int c)
235 {
236 // 4.12 fixed-point format
237 r = (short)((c & 0x00FF0000) >> 12);
238 g = (short)((c & 0x0000FF00) >> 4);
239 b = (short)((c & 0x000000FF) << 4);
240 a = (short)((c & 0xFF000000) >> 20);
241 }
242
243 template<>
244 inline Color<byte>::Color(unsigned int c)
245 {
246 r = (byte)((c & 0x00FF0000) >> 16);
247 g = (byte)((c & 0x0000FF00) >> 8);
248 b = (byte)((c & 0x000000FF) >> 0);
249 a = (byte)((c & 0xFF000000) >> 24);
250 }
251
252 template<>
253 inline Color<float>::Color(unsigned long c)
254 {
255 const float d = 1.0f / 255.0f;
256
257 r = (float)((c & 0x00FF0000) >> 16) * d;
258 g = (float)((c & 0x0000FF00) >> 8) * d;
259 b = (float)((c & 0x000000FF) >> 0) * d;
260 a = (float)((c & 0xFF000000) >> 24) * d;
261 }
262
263 template<>
264 inline Color<short>::Color(unsigned long c)
265 {
266 // 4.12 fixed-point format
267 r = (short)((c & 0x00FF0000) >> 12);
268 g = (short)((c & 0x0000FF00) >> 4);
269 b = (short)((c & 0x000000FF) << 4);
270 a = (short)((c & 0xFF000000) >> 20);
271 }
272
273 template<>
274 inline Color<byte>::Color(unsigned long c)
275 {
276 r = (byte)((c & 0x00FF0000) >> 16);
277 g = (byte)((c & 0x0000FF00) >> 8);
278 b = (byte)((c & 0x000000FF) >> 0);
279 a = (byte)((c & 0xFF000000) >> 24);
280 }
281
282 template<class T>
283 inline Color<T>::Color(T r_, T g_, T b_, T a_)
284 {
285 r = r_;
286 g = g_;
287 b = b_;
288 a = a_;
289 }
290
291 template<>
292 inline Color<float>::operator unsigned int() const
293 {
294 return ((unsigned int)min(b * 255.0f, 255.0f) << 0) |
295 ((unsigned int)min(g * 255.0f, 255.0f) << 8) |
296 ((unsigned int)min(r * 255.0f, 255.0f) << 16) |
297 ((unsigned int)min(a * 255.0f, 255.0f) << 24);
298 }
299
300 template<>
301 inline Color<short>::operator unsigned int() const
302 {
303 return ((unsigned int)min(b >> 4, 255) << 0) |
304 ((unsigned int)min(g >> 4, 255) << 8) |
305 ((unsigned int)min(r >> 4, 255) << 16) |
306 ((unsigned int)min(a >> 4, 255) << 24);
307 }
308
309 template<>
310 inline Color<byte>::operator unsigned int() const
311 {
312 return (b << 0) +
313 (g << 8) +
314 (r << 16) +
315 (a << 24);
316 }
317
318 template<class T>
319 inline T &Color<T>::operator[](int i)
320 {
321 return (&r)[i];
322 }
323
324 template<class T>
325 inline const T &Color<T>::operator[](int i) const
326 {
327 return (&r)[i];
328 }
329
330 template<class T>
331 inline Color<T> Color<T>::operator+() const
332 {
333 return *this;
334 }
335
336 template<class T>
337 inline Color<T> Color<T>::operator-() const
338 {
339 return Color(-r, -g, -b, -a);
340 }
341
342 template<class T>
343 inline Color<T> &Color<T>::operator=(const Color& c)
344 {
345 r = c.r;
346 g = c.g;
347 b = c.b;
348 a = c.a;
349
350 return *this;
351 }
352
353 template<class T>
354 inline Color<T> &Color<T>::operator+=(const Color &c)
355 {
356 r += c.r;
357 g += c.g;
358 b += c.b;
359 a += c.a;
360
361 return *this;
362 }
363
364 template<class T>
365 inline Color<T> &Color<T>::operator*=(float l)
366 {
367 *this = l * *this;
368
369 return *this;
370 }
371
372 template<class T>
373 inline Color<T> operator+(const Color<T> &c1, const Color<T> &c2)
374 {
375 return Color<T>(c1.r + c2.r,
376 c1.g + c2.g,
377 c1.b + c2.b,
378 c1.a + c2.a);
379 }
380
381 template<class T>
382 inline Color<T> operator-(const Color<T> &c1, const Color<T> &c2)
383 {
384 return Color<T>(c1.r - c2.r,
385 c1.g - c2.g,
386 c1.b - c2.b,
387 c1.a - c2.a);
388 }
389
390 template<class T>
391 inline Color<T> operator*(float l, const Color<T> &c)
392 {
393 T r = (T)(l * c.r);
394 T g = (T)(l * c.g);
395 T b = (T)(l * c.b);
396 T a = (T)(l * c.a);
397
398 return Color<T>(r, g, b, a);
399 }
400
401 template<class T>
402 inline Color<T> operator*(const Color<T> &c1, const Color<T> &c2)
403 {
404 T r = c1.r * c2.r;
405 T g = c1.g * c2.g;
406 T b = c1.b * c2.b;
407 T a = c1.a * c2.a;
408
409 return Color<T>(r, g, b, a);
410 }
411
412 template<>
413 inline Color<short> operator*(const Color<short> &c1, const Color<short> &c2)
414 {
415 short r = c1.r * c2.r >> 12;
416 short g = c1.g * c2.g >> 12;
417 short b = c1.b * c2.b >> 12;
418 short a = c1.a * c2.a >> 12;
419
420 return Color<short>(r, g, b, a);
421 }
422
423 template<>
424 inline Color<byte> operator*(const Color<byte> &c1, const Color<byte> &c2)
425 {
426 byte r = c1.r * c2.r >> 8;
427 byte g = c1.g * c2.g >> 8;
428 byte b = c1.b * c2.b >> 8;
429 byte a = c1.a * c2.a >> 8;
430
431 return Color<byte>(r, g, b, a);
432 }
433
434 template<class T>
435 inline Color<T> operator/(const Color<T> &c, float l)
436 {
437 l = 1.0f / l;
438
439 T r = (T)(l * c.r);
440 T g = (T)(l * c.g);
441 T b = (T)(l * c.b);
442 T a = (T)(l * c.a);
443
444 return Color<T>(r, g, b, a);
445 }
446
447 template<class T>
448 inline Color<T> Color<T>::gradient(const Color<T> &c1, const Color<T> &c2, float d)
449 {
450 d = 1.0f / d;
451
452 T r = (c2.r - c1.r) * d;
453 T g = (c2.g - c1.g) * d;
454 T b = (c2.b - c1.b) * d;
455 T a = (c2.a - c1.a) * d;
456
457 return Color<T>(r, g, b, a);
458 }
459
460 template<class T>
461 inline Color<T> Color<T>::shade(const Color<T> &c1, const Color<T> &c2, float d)
462 {
463 T r = c1.r + (T)(d * (c2.r - c1.r));
464 T g = c1.g + (T)(d * (c2.g - c1.g));
465 T b = c1.b + (T)(d * (c2.b - c1.b));
466 T a = c1.a + (T)(d * (c2.a - c1.a));
467
468 return Color<T>(r, g, b, a);
469 }
470}
471
472#endif // sw_Color_hpp
473