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 | |
21 | namespace 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 | |
76 | namespace 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 | |