1 /*
2 C-Dogs SDL
3 A port of the legendary (and fun) action/arcade cdogs.
4
5 Copyright (c) 2013-2018 Cong Xu
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10
11 Redistributions of source code must retain the above copyright notice, this
12 list of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28 */
29 #include "color.h"
30
31 #include <math.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "utils.h"
36
37 color_t colorWhite = { 255, 255, 255, 255 };
38 color_t colorRed = { 255, 0, 0, 255 };
39 color_t colorGreen = { 0, 255, 0, 255 };
40 color_t colorBlue = { 0, 0, 255, 255 };
41 color_t colorPoison = { 64, 192, 64, 255 };
42 color_t colorBlack = { 0, 0, 0, 255 };
43 color_t colorDarker = { 192, 192, 192, 255 };
44 color_t colorPurple = { 192, 0, 192, 255 };
45 color_t colorGray = { 128, 128, 128, 255 };
46 color_t colorYellow = { 255, 255, 128, 255 };
47 color_t colorMagenta = { 255, 0, 255, 255 };
48 color_t colorCyan = { 0, 255, 255, 255 };
49 color_t colorFog = { 96, 96, 96, 255 };
50 color_t colorOrange = { 255, 128, 0, 255 };
51 color_t colorTransparent = { 0, 0, 0, 0 };
52
53 color_t colorMaroon = { 0x84, 0, 0, 255 };
54 color_t colorLonestar = { 0x70, 0, 0, 255 };
55 color_t colorRusticRed = { 0x48, 0, 0, 255 };
56 color_t colorOfficeGreen = { 0, 0x84, 0, 255 };
57 color_t colorPakistanGreen = { 0, 0x70, 0, 255 };
58 color_t colorDarkFern = { 0, 0x48, 0, 255 };
59 color_t colorNavyBlue = { 0, 0, 0x84, 255 };
60 color_t colorArapawa = { 0, 0, 0x70, 255 };
61 color_t colorStratos = { 0, 0, 0x48, 255 };
62 color_t colorPatriarch = { 0x84, 0, 0x84, 255 };
63 color_t colorPompadour = { 0x70, 0, 0x70, 255 };
64 color_t colorLoulou = { 0x48, 0, 0x48, 255 };
65 color_t colorBattleshipGrey = { 0x84, 0x84, 0x84, 255 };
66 color_t colorDoveGray = { 0x70, 0x70, 0x70, 255 };
67 color_t colorGravel = { 0x48, 0x48, 0x48, 255 };
68 color_t colorComet = { 0x5C, 0x5C, 0x84, 255 };
69 color_t colorFiord = { 0x48, 0x48, 0x70, 255 };
70 color_t colorTuna = { 0x34, 0x34, 0x48, 255 };
71 color_t colorHacienda = { 0x94, 0x80, 0x2C, 255 };
72 color_t colorKumera = { 0x84, 0x70, 0x24, 255 };
73 color_t colorHimalaya = { 0x74, 0x60, 0x1C, 255 };
74 color_t colorChocolate = { 0x84, 0x44, 0, 255 };
75 color_t colorNutmeg = { 0x70, 0x38, 0, 255 };
76 color_t colorBracken = { 0x48, 0x24, 0, 255 };
77 color_t colorTeal = { 0, 0x84, 0x84, 255 };
78 color_t colorSkobeloff = { 0, 0x70, 0x70, 255 };
79 color_t colorDeepJungleGreen = { 0, 0x48, 0x48, 255 };
80
81 color_t colorSkin = { 0xF4, 0x94, 0x4C, 255 };
82 color_t colorDarkSkin = { 0x93, 0x5D, 0x37, 255 };
83 color_t colorAsianSkin = { 0xFF, 0xCC, 0x99, 255 };
84
85 color_t colorLightBlue = { 80, 80, 160, 255 };
86
ColorMult(color_t c,color_t m)87 color_t ColorMult(color_t c, color_t m)
88 {
89 c.r = (uint8_t)((int)c.r * m.r / 255);
90 c.g = (uint8_t)((int)c.g * m.g / 255);
91 c.b = (uint8_t)((int)c.b * m.b / 255);
92 c.a = (uint8_t)((int)c.a * m.a / 255);
93 return c;
94 }
ColorAlphaBlend(color_t a,color_t b)95 color_t ColorAlphaBlend(color_t a, color_t b)
96 {
97 a.r = (uint8_t)(((int)a.r*(255 - b.a) + (int)b.r*b.a)/255);
98 a.g = (uint8_t)(((int)a.g*(255 - b.a) + (int)b.g*b.a)/255);
99 a.b = (uint8_t)(((int)a.b*(255 - b.a) + (int)b.b*b.a)/255);
100 a.a = 255;
101 return a;
102 }
103
104 HSV tintNone = { -1.0, 1.0, 1.0 };
105 HSV tintRed = { 0.0, 1.0, 1.0 };
106 HSV tintYellow = { 60.0, 1.0, 1.0 };
107 HSV tintGreen = { 120.0, 1.0, 1.0 };
108 HSV tintCyan = { 180.0, 1.0, 1.0 };
109 HSV tintPoison = { 120.0, 0.33, 2.0 };
110 HSV tintGray = { -1.0, 0.0, 1.0 };
111 HSV tintPurple = { 300, 1.0, 1.0 };
112 HSV tintDarker = { -1.0, 1.0, 0.75 };
113
ColorTint(color_t c,HSV hsv)114 color_t ColorTint(color_t c, HSV hsv)
115 {
116 // Adapted from answer by David H
117 // http://stackoverflow.com/a/6930407/2038264
118 // License: http://creativecommons.org/licenses/by-sa/3.0/
119 // Author profile: http://stackoverflow.com/users/1633251/david-h
120 color_t out;
121 int vAvg = ((int)c.r + c.g + c.b) / 3;
122 uint8_t vComponent = (uint8_t)CLAMP(hsv.v * vAvg, 0, 255);
123
124 if (hsv.s <= 0.0)
125 {
126 // No saturation; just gray
127 out.r = vComponent;
128 out.g = vComponent;
129 out.b = vComponent;
130 }
131 else if (hsv.h >= 0)
132 {
133 // set hue to h; use regular HSV to RGB conversion
134 double ff;
135 uint8_t p, q, t;
136 long i;
137 double hh = hsv.h;
138 if (hh >= 360.0)
139 {
140 hh = 0.0;
141 }
142 hh /= 60.0;
143 i = (long)hh;
144 ff = hh - i;
145 p = (uint8_t)CLAMP(vComponent * (1.0 - hsv.s), 0, 255);
146 q = (uint8_t)CLAMP(vComponent * (1.0 - (hsv.s * ff)), 0, 255);
147 t = (uint8_t)CLAMP(vComponent * (1.0 - (hsv.s * (1.0 - ff))), 0, 255);
148
149 switch(i)
150 {
151 case 0:
152 out.r = vComponent;
153 out.g = t;
154 out.b = p;
155 break;
156 case 1:
157 out.r = q;
158 out.g = vComponent;
159 out.b = p;
160 break;
161 case 2:
162 out.r = p;
163 out.g = vComponent;
164 out.b = t;
165 break;
166
167 case 3:
168 out.r = p;
169 out.g = q;
170 out.b = vComponent;
171 break;
172 case 4:
173 out.r = t;
174 out.g = p;
175 out.b = vComponent;
176 break;
177 case 5:
178 default:
179 out.r = vComponent;
180 out.g = p;
181 out.b = q;
182 break;
183 }
184 }
185 else
186 {
187 // Just set saturation and value
188 // Use weighted average to shift components towards grey for saturation
189 out.r = (uint8_t)CLAMP(hsv.v * (vAvg*(1.0-hsv.s) + hsv.s*c.r), 0, 255);
190 out.g = (uint8_t)CLAMP(hsv.v * (vAvg*(1.0-hsv.s) + hsv.s*c.g), 0, 255);
191 out.b = (uint8_t)CLAMP(hsv.v * (vAvg*(1.0-hsv.s) + hsv.s*c.b), 0, 255);
192 }
193 out.a = c.a;
194 return out;
195 }
196
ColorEquals(const color_t a,const color_t b)197 bool ColorEquals(const color_t a, const color_t b)
198 {
199 return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
200 }
HSVEquals(const HSV a,const HSV b)201 bool HSVEquals(const HSV a, const HSV b)
202 {
203 const double epsilon = 0.000001;
204 return fabs(a.h - b.h) < epsilon && fabs(a.s - b.s) < epsilon &&
205 fabs(a.v - b.v) < epsilon;
206 }
207
StrColor(const char * s)208 color_t StrColor(const char *s)
209 {
210 if (s == NULL)
211 {
212 return colorBlack;
213 }
214 const int len = (int)strlen(s);
215 if (len != 6 && len != 8)
216 {
217 return colorBlack;
218 }
219 long long hex = strtoll(s, NULL, 16);
220 color_t c;
221 if (len == 6)
222 {
223 c.a = 255;
224 }
225 else
226 {
227 c.a = hex & 255;
228 hex >>= 8;
229 }
230 c.r = (hex >> 16) & 255;
231 c.g = (hex >> 8) & 255;
232 c.b = hex & 255;
233 return c;
234 }
ColorStr(char * s,const color_t c)235 void ColorStr(char *s, const color_t c)
236 {
237 sprintf(s, "%02x%02x%02x%02x", c.r, c.g, c.b, c.a);
238 }
239