1 #region Copyright & License Information
2 /*
3  * Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
4  * This file is part of OpenRA, which is free software. It is made
5  * available to you under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version. For more
8  * information, see COPYING.
9  */
10 #endregion
11 
12 using System;
13 using System.Globalization;
14 using OpenRA.Scripting;
15 
16 namespace OpenRA.Primitives
17 {
18 	public struct Color : IEquatable<Color>, IScriptBindable
19 	{
20 		readonly long argb;
21 
FromArgbOpenRA.Primitives.Color22 		public static Color FromArgb(int red, int green, int blue)
23 		{
24 			return FromArgb(byte.MaxValue, red, green, blue);
25 		}
26 
FromArgbOpenRA.Primitives.Color27 		public static Color FromArgb(int alpha, int red, int green, int blue)
28 		{
29 			return new Color(((byte)alpha << 24) + ((byte)red << 16) + ((byte)green << 8) + (byte)blue);
30 		}
31 
FromAhslOpenRA.Primitives.Color32 		public static Color FromAhsl(int alpha, float h, float s, float l)
33 		{
34 			// Convert from HSL to RGB
35 			var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
36 			var p = 2 * l - q;
37 
38 			float[] trgb = { h + 1 / 3.0f, h, h - 1 / 3.0f };
39 			float[] rgb = { 0, 0, 0 };
40 
41 			for (var k = 0; k < 3; k++)
42 			{
43 				while (trgb[k] < 0) trgb[k] += 1.0f;
44 				while (trgb[k] > 1) trgb[k] -= 1.0f;
45 			}
46 
47 			for (var k = 0; k < 3; k++)
48 			{
49 				if (trgb[k] < 1 / 6.0f)
50 					rgb[k] = p + ((q - p) * 6 * trgb[k]);
51 				else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5)
52 					rgb[k] = q;
53 				else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3)
54 					rgb[k] = p + ((q - p) * 6 * (2.0f / 3 - trgb[k]));
55 				else
56 					rgb[k] = p;
57 			}
58 
59 			return FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
60 		}
61 
FromAhslOpenRA.Primitives.Color62 		public static Color FromAhsl(int h, int s, int l)
63 		{
64 			return FromAhsl(255, h / 255f, s / 255f, l / 255f);
65 		}
66 
FromAhslOpenRA.Primitives.Color67 		public static Color FromAhsl(float h, float s, float l)
68 		{
69 			return FromAhsl(255, h, s, l);
70 		}
71 
FromAhsvOpenRA.Primitives.Color72 		public static Color FromAhsv(int alpha, float h, float s, float v)
73 		{
74 			var ll = 0.5f * (2 - s) * v;
75 			var ss = (ll >= 1 || v <= 0) ? 0 : 0.5f * s * v / (ll <= 0.5f ? ll : 1 - ll);
76 			return FromAhsl(alpha, h, ss, ll);
77 		}
78 
FromAhsvOpenRA.Primitives.Color79 		public static Color FromAhsv(float h, float s, float v)
80 		{
81 			return FromAhsv(255, h, s, v);
82 		}
83 
ToAhsvOpenRA.Primitives.Color84 		public void ToAhsv(out int a, out float h, out float s, out float v)
85 		{
86 			var ll = 2 * GetBrightness();
87 			var ss = GetSaturation() * ((ll <= 1) ? ll : 2 - ll);
88 
89 			a = A;
90 			h = GetHue() / 360f;
91 			s = (2 * ss) / (ll + ss);
92 			v = (ll + ss) / 2;
93 		}
94 
ColorOpenRA.Primitives.Color95 		Color(long argb)
96 		{
97 			this.argb = argb;
98 		}
99 
ToArgbOpenRA.Primitives.Color100 		public int ToArgb()
101 		{
102 			return (int)argb;
103 		}
104 
FromArgbOpenRA.Primitives.Color105 		public static Color FromArgb(int alpha, Color baseColor)
106 		{
107 			return FromArgb(alpha, baseColor.R, baseColor.G, baseColor.B);
108 		}
109 
FromArgbOpenRA.Primitives.Color110 		public static Color FromArgb(int argb)
111 		{
112 			return FromArgb((byte)(argb >> 24), (byte)(argb >> 16), (byte)(argb >> 8), (byte)argb);
113 		}
114 
FromArgbOpenRA.Primitives.Color115 		public static Color FromArgb(uint argb)
116 		{
117 			return FromArgb((byte)(argb >> 24), (byte)(argb >> 16), (byte)(argb >> 8), (byte)argb);
118 		}
119 
TryParseOpenRA.Primitives.Color120 		public static bool TryParse(string value, out Color color)
121 		{
122 			color = default(Color);
123 			value = value.Trim();
124 			if (value.Length != 6 && value.Length != 8)
125 				return false;
126 
127 			byte red, green, blue, alpha = 255;
128 			if (!byte.TryParse(value.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out red)
129 			    || !byte.TryParse(value.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out green)
130 			    || !byte.TryParse(value.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out blue))
131 				return false;
132 
133 			if (value.Length == 8
134 			    && !byte.TryParse(value.Substring(6, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out alpha))
135 				return false;
136 
137 			color = FromArgb(alpha, red, green, blue);
138 			return true;
139 		}
140 
operator ==OpenRA.Primitives.Color141 		public static bool operator ==(Color left, Color right)
142 		{
143 			return left.argb == right.argb;
144 		}
145 
operator !=OpenRA.Primitives.Color146 		public static bool operator !=(Color left, Color right)
147 		{
148 			return !(left == right);
149 		}
150 
GetBrightnessOpenRA.Primitives.Color151 		public float GetBrightness()
152 		{
153 			var min = Math.Min(R, Math.Min(G, B));
154 			var max = Math.Max(R, Math.Max(G, B));
155 			return (max + min) / 510f;
156 		}
157 
GetSaturationOpenRA.Primitives.Color158 		public float GetSaturation()
159 		{
160 			var min = Math.Min(R, Math.Min(G, B));
161 			var max = Math.Max(R, Math.Max(G, B));
162 			if (max == min)
163 				return 0.0f;
164 
165 			var sum = max + min;
166 			if (sum > byte.MaxValue)
167 				sum = 510 - sum;
168 
169 			return (float)(max - min) / sum;
170 		}
171 
GetHueOpenRA.Primitives.Color172 		public float GetHue()
173 		{
174 			var min = Math.Min(R, Math.Min(G, B));
175 			var max = Math.Max(R, Math.Max(G, B));
176 			if (max == min)
177 				return 0.0f;
178 
179 			var diff = (float)(max - min);
180 			var rNorm = (max - R) / diff;
181 			var gNorm = (max - G) / diff;
182 			var bNorm = (max - B) / diff;
183 
184 			var hue = 0.0f;
185 			if (R == max)
186 				hue = 60.0f * (6.0f + bNorm - gNorm);
187 			if (G == max)
188 				hue = 60.0f * (2.0f + rNorm - bNorm);
189 			if (B == max)
190 				hue = 60.0f * (4.0f + gNorm - rNorm);
191 
192 			if (hue > 360.0f)
193 				hue -= 360f;
194 
195 			return hue;
196 		}
197 
198 		public byte A { get { return (byte)(argb >> 24); } }
199 		public byte R { get { return (byte)(argb >> 16); } }
200 		public byte G { get { return (byte)(argb >> 8); } }
201 		public byte B { get { return (byte)argb; } }
202 
EqualsOpenRA.Primitives.Color203 		public bool Equals(Color other)
204 		{
205 			return this == other;
206 		}
207 
EqualsOpenRA.Primitives.Color208 		public override bool Equals(object obj)
209 		{
210 			if (!(obj is Color))
211 				return false;
212 
213 			return this == (Color)obj;
214 		}
215 
GetHashCodeOpenRA.Primitives.Color216 		public override int GetHashCode()
217 		{
218 			return (int)(argb ^ argb >> 32);
219 		}
220 
ToStringOpenRA.Primitives.Color221 		public override string ToString()
222 		{
223 			if (A == 255)
224 				return R.ToString("X2") + G.ToString("X2") + B.ToString("X2");
225 
226 			return R.ToString("X2") + G.ToString("X2") + B.ToString("X2") + A.ToString("X2");
227 		}
228 
229 		public static Color Transparent { get { return FromArgb(0x00FFFFFF); } }
230 		public static Color AliceBlue { get { return FromArgb(0xFFF0F8FF); } }
231 		public static Color AntiqueWhite { get { return FromArgb(0xFFFAEBD7); } }
232 		public static Color Aqua { get { return FromArgb(0xFF00FFFF); } }
233 		public static Color Aquamarine { get { return FromArgb(0xFF7FFFD4); } }
234 		public static Color Azure { get { return FromArgb(0xFFF0FFFF); } }
235 		public static Color Beige { get { return FromArgb(0xFFF5F5DC); } }
236 		public static Color Bisque { get { return FromArgb(0xFFFFE4C4); } }
237 		public static Color Black { get { return FromArgb(0xFF000000); } }
238 		public static Color BlanchedAlmond { get { return FromArgb(0xFFFFEBCD); } }
239 		public static Color Blue { get { return FromArgb(0xFF0000FF); } }
240 		public static Color BlueViolet { get { return FromArgb(0xFF8A2BE2); } }
241 		public static Color Brown { get { return FromArgb(0xFFA52A2A); } }
242 		public static Color BurlyWood { get { return FromArgb(0xFFDEB887); } }
243 		public static Color CadetBlue { get { return FromArgb(0xFF5F9EA0); } }
244 		public static Color Chartreuse { get { return FromArgb(0xFF7FFF00); } }
245 		public static Color Chocolate { get { return FromArgb(0xFFD2691E); } }
246 		public static Color Coral { get { return FromArgb(0xFFFF7F50); } }
247 		public static Color CornflowerBlue { get { return FromArgb(0xFF6495ED); } }
248 		public static Color Cornsilk { get { return FromArgb(0xFFFFF8DC); } }
249 		public static Color Crimson { get { return FromArgb(0xFFDC143C); } }
250 		public static Color Cyan { get { return FromArgb(0xFF00FFFF); } }
251 		public static Color DarkBlue { get { return FromArgb(0xFF00008B); } }
252 		public static Color DarkCyan { get { return FromArgb(0xFF008B8B); } }
253 		public static Color DarkGoldenrod { get { return FromArgb(0xFFB8860B); } }
254 		public static Color DarkGray { get { return FromArgb(0xFFA9A9A9); } }
255 		public static Color DarkGreen { get { return FromArgb(0xFF006400); } }
256 		public static Color DarkKhaki { get { return FromArgb(0xFFBDB76B); } }
257 		public static Color DarkMagenta { get { return FromArgb(0xFF8B008B); } }
258 		public static Color DarkOliveGreen { get { return FromArgb(0xFF556B2F); } }
259 		public static Color DarkOrange { get { return FromArgb(0xFFFF8C00); } }
260 		public static Color DarkOrchid { get { return FromArgb(0xFF9932CC); } }
261 		public static Color DarkRed { get { return FromArgb(0xFF8B0000); } }
262 		public static Color DarkSalmon { get { return FromArgb(0xFFE9967A); } }
263 		public static Color DarkSeaGreen { get { return FromArgb(0xFF8FBC8B); } }
264 		public static Color DarkSlateBlue { get { return FromArgb(0xFF483D8B); } }
265 		public static Color DarkSlateGray { get { return FromArgb(0xFF2F4F4F); } }
266 		public static Color DarkTurquoise { get { return FromArgb(0xFF00CED1); } }
267 		public static Color DarkViolet { get { return FromArgb(0xFF9400D3); } }
268 		public static Color DeepPink { get { return FromArgb(0xFFFF1493); } }
269 		public static Color DeepSkyBlue { get { return FromArgb(0xFF00BFFF); } }
270 		public static Color DimGray { get { return FromArgb(0xFF696969); } }
271 		public static Color DodgerBlue { get { return FromArgb(0xFF1E90FF); } }
272 		public static Color Firebrick { get { return FromArgb(0xFFB22222); } }
273 		public static Color FloralWhite { get { return FromArgb(0xFFFFFAF0); } }
274 		public static Color ForestGreen { get { return FromArgb(0xFF228B22); } }
275 		public static Color Fuchsia { get { return FromArgb(0xFFFF00FF); } }
276 		public static Color Gainsboro { get { return FromArgb(0xFFDCDCDC); } }
277 		public static Color GhostWhite { get { return FromArgb(0xFFF8F8FF); } }
278 		public static Color Gold { get { return FromArgb(0xFFFFD700); } }
279 		public static Color Goldenrod { get { return FromArgb(0xFFDAA520); } }
280 		public static Color Gray { get { return FromArgb(0xFF808080); } }
281 		public static Color Green { get { return FromArgb(0xFF008000); } }
282 		public static Color GreenYellow { get { return FromArgb(0xFFADFF2F); } }
283 		public static Color Honeydew { get { return FromArgb(0xFFF0FFF0); } }
284 		public static Color HotPink { get { return FromArgb(0xFFFF69B4); } }
285 		public static Color IndianRed { get { return FromArgb(0xFFCD5C5C); } }
286 		public static Color Indigo { get { return FromArgb(0xFF4B0082); } }
287 		public static Color Ivory { get { return FromArgb(0xFFFFFFF0); } }
288 		public static Color Khaki { get { return FromArgb(0xFFF0E68C); } }
289 		public static Color Lavender { get { return FromArgb(0xFFE6E6FA); } }
290 		public static Color LavenderBlush { get { return FromArgb(0xFFFFF0F5); } }
291 		public static Color LawnGreen { get { return FromArgb(0xFF7CFC00); } }
292 		public static Color LemonChiffon { get { return FromArgb(0xFFFFFACD); } }
293 		public static Color LightBlue { get { return FromArgb(0xFFADD8E6); } }
294 		public static Color LightCoral { get { return FromArgb(0xFFF08080); } }
295 		public static Color LightCyan { get { return FromArgb(0xFFE0FFFF); } }
296 		public static Color LightGoldenrodYellow { get { return FromArgb(0xFFFAFAD2); } }
297 		public static Color LightGray { get { return FromArgb(0xFFD3D3D3); } }
298 		public static Color LightGreen { get { return FromArgb(0xFF90EE90); } }
299 		public static Color LightPink { get { return FromArgb(0xFFFFB6C1); } }
300 		public static Color LightSalmon { get { return FromArgb(0xFFFFA07A); } }
301 		public static Color LightSeaGreen { get { return FromArgb(0xFF20B2AA); } }
302 		public static Color LightSkyBlue { get { return FromArgb(0xFF87CEFA); } }
303 		public static Color LightSlateGray { get { return FromArgb(0xFF778899); } }
304 		public static Color LightSteelBlue { get { return FromArgb(0xFFB0C4DE); } }
305 		public static Color LightYellow { get { return FromArgb(0xFFFFFFE0); } }
306 		public static Color Lime { get { return FromArgb(0xFF00FF00); } }
307 		public static Color LimeGreen { get { return FromArgb(0xFF32CD32); } }
308 		public static Color Linen { get { return FromArgb(0xFFFAF0E6); } }
309 		public static Color Magenta { get { return FromArgb(0xFFFF00FF); } }
310 		public static Color Maroon { get { return FromArgb(0xFF800000); } }
311 		public static Color MediumAquamarine { get { return FromArgb(0xFF66CDAA); } }
312 		public static Color MediumBlue { get { return FromArgb(0xFF0000CD); } }
313 		public static Color MediumOrchid { get { return FromArgb(0xFFBA55D3); } }
314 		public static Color MediumPurple { get { return FromArgb(0xFF9370DB); } }
315 		public static Color MediumSeaGreen { get { return FromArgb(0xFF3CB371); } }
316 		public static Color MediumSlateBlue { get { return FromArgb(0xFF7B68EE); } }
317 		public static Color MediumSpringGreen { get { return FromArgb(0xFF00FA9A); } }
318 		public static Color MediumTurquoise { get { return FromArgb(0xFF48D1CC); } }
319 		public static Color MediumVioletRed { get { return FromArgb(0xFFC71585); } }
320 		public static Color MidnightBlue { get { return FromArgb(0xFF191970); } }
321 		public static Color MintCream { get { return FromArgb(0xFFF5FFFA); } }
322 		public static Color MistyRose { get { return FromArgb(0xFFFFE4E1); } }
323 		public static Color Moccasin { get { return FromArgb(0xFFFFE4B5); } }
324 		public static Color NavajoWhite { get { return FromArgb(0xFFFFDEAD); } }
325 		public static Color Navy { get { return FromArgb(0xFF000080); } }
326 		public static Color OldLace { get { return FromArgb(0xFFFDF5E6); } }
327 		public static Color Olive { get { return FromArgb(0xFF808000); } }
328 		public static Color OliveDrab { get { return FromArgb(0xFF6B8E23); } }
329 		public static Color Orange { get { return FromArgb(0xFFFFA500); } }
330 		public static Color OrangeRed { get { return FromArgb(0xFFFF4500); } }
331 		public static Color Orchid { get { return FromArgb(0xFFDA70D6); } }
332 		public static Color PaleGoldenrod { get { return FromArgb(0xFFEEE8AA); } }
333 		public static Color PaleGreen { get { return FromArgb(0xFF98FB98); } }
334 		public static Color PaleTurquoise { get { return FromArgb(0xFFAFEEEE); } }
335 		public static Color PaleVioletRed { get { return FromArgb(0xFFDB7093); } }
336 		public static Color PapayaWhip { get { return FromArgb(0xFFFFEFD5); } }
337 		public static Color PeachPuff { get { return FromArgb(0xFFFFDAB9); } }
338 		public static Color Peru { get { return FromArgb(0xFFCD853F); } }
339 		public static Color Pink { get { return FromArgb(0xFFFFC0CB); } }
340 		public static Color Plum { get { return FromArgb(0xFFDDA0DD); } }
341 		public static Color PowderBlue { get { return FromArgb(0xFFB0E0E6); } }
342 		public static Color Purple { get { return FromArgb(0xFF800080); } }
343 		public static Color Red { get { return FromArgb(0xFFFF0000); } }
344 		public static Color RosyBrown { get { return FromArgb(0xFFBC8F8F); } }
345 		public static Color RoyalBlue { get { return FromArgb(0xFF4169E1); } }
346 		public static Color SaddleBrown { get { return FromArgb(0xFF8B4513); } }
347 		public static Color Salmon { get { return FromArgb(0xFFFA8072); } }
348 		public static Color SandyBrown { get { return FromArgb(0xFFF4A460); } }
349 		public static Color SeaGreen { get { return FromArgb(0xFF2E8B57); } }
350 		public static Color SeaShell { get { return FromArgb(0xFFFFF5EE); } }
351 		public static Color Sienna { get { return FromArgb(0xFFA0522D); } }
352 		public static Color Silver { get { return FromArgb(0xFFC0C0C0); } }
353 		public static Color SkyBlue { get { return FromArgb(0xFF87CEEB); } }
354 		public static Color SlateBlue { get { return FromArgb(0xFF6A5ACD); } }
355 		public static Color SlateGray { get { return FromArgb(0xFF708090); } }
356 		public static Color Snow { get { return FromArgb(0xFFFFFAFA); } }
357 		public static Color SpringGreen { get { return FromArgb(0xFF00FF7F); } }
358 		public static Color SteelBlue { get { return FromArgb(0xFF4682B4); } }
359 		public static Color Tan { get { return FromArgb(0xFFD2B48C); } }
360 		public static Color Teal { get { return FromArgb(0xFF008080); } }
361 		public static Color Thistle { get { return FromArgb(0xFFD8BFD8); } }
362 		public static Color Tomato { get { return FromArgb(0xFFFF6347); } }
363 		public static Color Turquoise { get { return FromArgb(0xFF40E0D0); } }
364 		public static Color Violet { get { return FromArgb(0xFFEE82EE); } }
365 		public static Color Wheat { get { return FromArgb(0xFFF5DEB3); } }
366 		public static Color White { get { return FromArgb(0xFFFFFFFF); } }
367 		public static Color WhiteSmoke { get { return FromArgb(0xFFF5F5F5); } }
368 		public static Color Yellow { get { return FromArgb(0xFFFFFF00); } }
369 		public static Color YellowGreen { get { return FromArgb(0xFF9ACD32); } }
370 	}
371 }
372