1 /* 2 DSFML - The Simple and Fast Multimedia Library for D 3 4 Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 6 This software is provided 'as-is', without any express or implied warranty. 7 In no event will the authors be held liable for any damages arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, including commercial applications, 10 and to alter it and redistribute it freely, subject to the following restrictions: 11 12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. 13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 14 15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 16 17 3. This notice may not be removed or altered from any source distribution 18 */ 19 20 module dsfml.graphics.color; 21 22 import std.math, std.traits; 23 24 import std.algorithm; 25 26 /++ 27 + Color is a utility struct for manipulating 32-bits RGBA colors. 28 + 29 + Authors: Laurent Gomila, Jeremy DeHaan 30 + See_Also: http://sfml-dev.org/documentation/2.0/classsf_1_1Color.php#details 31 +/ 32 struct Color 33 { 34 ubyte r; /// Red component 35 ubyte g; /// Green component 36 ubyte b; /// Blue component 37 ubyte a = 255; /// Alpha component 38 39 static immutable Black = Color(0, 0, 0, 255); 40 static immutable White = Color(255, 255, 255, 255); 41 static immutable Red = Color(255, 0, 0, 255); 42 static immutable Green = Color(0, 255, 0,255); 43 static immutable Blue = Color(0, 0, 255,255); 44 static immutable Yellow = Color(255, 255, 0, 255); 45 static immutable Magenta = Color(255, 0, 255, 255); 46 static immutable Cyan = Color(0, 255, 255, 255); 47 static immutable Transparent = Color(0, 0, 0, 0); 48 49 string toString() const 50 { 51 import std.conv; 52 return "R: " ~ text(r) ~ " G: " ~ text(g) ~ " B: " ~ text(b) ~ " A: " ~ text(a); 53 } 54 55 Color opBinary(string op)(Color otherColor) const 56 if((op == "+") || (op == "-")) 57 { 58 static if(op == "+") 59 { 60 return Color(cast(ubyte)min(r+otherColor.r, 255), 61 cast(ubyte)min(g+otherColor.g, 255), 62 cast(ubyte)min(b+otherColor.b, 255), 63 cast(ubyte)min(a+otherColor.a, 255)); 64 } 65 static if(op == "-") 66 { 67 return Color(cast(ubyte)max(r-otherColor.r, 0), 68 cast(ubyte)max(g-otherColor.g, 0), 69 cast(ubyte)max(b-otherColor.b, 0), 70 cast(ubyte)max(a-otherColor.a, 0)); 71 } 72 } 73 74 Color opBinary(string op, E)(E num) const 75 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 76 { 77 static if(op == "*") 78 { 79 //actually dividing or multiplying by a negative 80 if(num < 1) 81 { 82 return Color(cast(ubyte)max(r*num, 0), 83 cast(ubyte)max(g*num, 0), 84 cast(ubyte)max(b*num, 0), 85 cast(ubyte)max(a*num, 0)); 86 } 87 else 88 { 89 return Color(cast(ubyte)min(r*num, 255), 90 cast(ubyte)min(g*num, 255), 91 cast(ubyte)min(b*num, 255), 92 cast(ubyte)min(a*num, 255)); 93 } 94 } 95 static if(op == "/") 96 { 97 //actually multiplying or dividing by a negative 98 if(num < 1) 99 { 100 return Color(cast(ubyte)min(r/num, 255), 101 cast(ubyte)min(g/num, 255), 102 cast(ubyte)min(b/num, 255), 103 cast(ubyte)min(a/num, 255)); 104 } 105 else 106 { 107 return Color(cast(ubyte)max(r/num, 0), 108 cast(ubyte)max(g/num, 0), 109 cast(ubyte)max(b/num, 0), 110 cast(ubyte)max(a/num, 0)); 111 } 112 } 113 } 114 115 ref Color opOpAssign(string op)(Color otherColor) 116 if((op == "+") || (op == "-")) 117 { 118 static if(op == "+") 119 { 120 r = cast(ubyte)min(r+otherColor.r, 255); 121 g = cast(ubyte)min(g+otherColor.g, 255); 122 b = cast(ubyte)min(b+otherColor.b, 255); 123 a = cast(ubyte)min(a+otherColor.a, 255); 124 return this; 125 } 126 static if(op == "-") 127 { 128 r = cast(ubyte)max(r-otherColor.r, 0); 129 g = cast(ubyte)max(g-otherColor.g, 0); 130 b = cast(ubyte)max(b-otherColor.b, 0); 131 a = cast(ubyte)max(a-otherColor.a, 0); 132 return this; 133 } 134 } 135 136 ref Color opOpAssign(string op, E)(E num) 137 if(isNumeric!(E) && ((op == "*") || (op == "/"))) 138 { 139 static if(op == "*") 140 { 141 //actually dividing or multiplying by a negative 142 if(num < 1) 143 { 144 r = cast(ubyte)max(r*num, 0); 145 g = cast(ubyte)max(g*num, 0); 146 b = cast(ubyte)max(b*num, 0); 147 a = cast(ubyte)max(a*num, 0); 148 } 149 else 150 { 151 r = cast(ubyte)min(r*num, 255); 152 g = cast(ubyte)min(g*num, 255); 153 b = cast(ubyte)min(b*num, 255); 154 a = cast(ubyte)min(a*num, 255); 155 } 156 157 return this; 158 } 159 static if(op == "/") 160 { 161 //actually multiplying or dividing by a negative 162 if( num < 1) 163 { 164 r = cast(ubyte)min(r/num, 255); 165 g = cast(ubyte)min(g/num, 255); 166 b = cast(ubyte)min(b/num, 255); 167 a = cast(ubyte)min(a/num, 255); 168 } 169 else 170 { 171 r = cast(ubyte)max(r/num, 0); 172 g = cast(ubyte)max(g/num, 0); 173 b = cast(ubyte)max(b/num, 0); 174 a = cast(ubyte)max(a/num, 0); 175 } 176 177 return this; 178 } 179 } 180 181 bool opEquals(Color otherColor) const 182 { 183 return ((r == otherColor.r) && (g == otherColor.g) && (b == otherColor.b) && (a == otherColor.a)); 184 } 185 } 186 187 unittest 188 { 189 version(DSFML_Unittest_Graphics) 190 { 191 import std.stdio; 192 193 writeln("Unit test for Color"); 194 195 //will perform arithmatic on Color to make sure everything works right. 196 197 Color color = Color(100,100,100, 100); 198 199 color*= 2;//(200, 200, 200, 200) 200 201 color = color *.5;//(100, 100, 100, 100) 202 203 color = color / 2;//(50, 50, 50, 50) 204 205 color/= 2;//(25, 25, 25, 25) 206 207 color+= Color(40,20,10,5);//(65,45, 35, 30) 208 209 210 color-= Color(5,10,20,40);//(60, 35, 15, 0) 211 212 color = color + Color(40, 20, 10, 5);//(100, 55, 25, 5) 213 214 color = color - Color(5, 10, 20, 40);//(95, 45, 5, 0) 215 216 assert(color == Color(95, 45, 5, 0)); 217 218 writeln(); 219 } 220 }