1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.Graphics.Color;
25 
26 private {
27 	debug import std.stdio : writeln;
28 	
29 	import derelict.sdl2.sdl;
30 }
31 
32 SDL_Color* transfer(const Color* col, SDL_Color* to) pure nothrow
33 in {
34 	assert(to !is null);
35 } body {
36 	if (col is null)
37 		return null;
38 	
39 	col.transferTo(to);
40 	
41 	return to;
42 }
43 
44 /**
45  * Color defines a structure which contains 4 ubyte values, each for red, green, blue and alpha.
46  * Alpha is default 255 (1.0).
47  *
48  * Author: rschuett
49  */
50 struct Color {
51 	static const Color Black   = Color(0,     0,   0); /** Black Color (0, 0, 0) */
52 	static const Color White   = Color(255, 255, 255); /** White Color (255, 255, 255) */
53 	static const Color Red     = Color(255,   0,   0); /** Red Color (255, 0, 0) */
54 	static const Color Green   = Color(0,   255,   0); /** Green Color (0, 255, 0) */
55 	static const Color Blue    = Color(0,     0, 255); /** Blue Color (0, 0, 255) */
56 	static const Color Cyan    = Color(0,   255, 255); /** Cyan Color (0, 255, 255) */
57 	static const Color Yellow  = Color(255, 255,   0); /** Yellow Color (255, 255, 0)*/
58 	static const Color Magenta = Color(255,   0, 255); /** Magenta Color (255, 0, 255) */
59 	static const Color Gray    = Color(0.7f, 0.7f, 0.7f); /** Gray Color (0.7, 0.7, 0.7) */
60 	
61 	/**
62 	 * The color components
63 	 */
64 	ubyte red, green, blue, alpha;
65 	
66 	/**
67 	 * CTor
68 	 */
69 	this(ubyte red, ubyte green, ubyte blue, ubyte alpha = 255) pure nothrow {
70 		this.red   = red;
71 		this.green = green;
72 		this.blue  = blue;
73 		this.alpha = alpha;
74 	}
75 	
76 	/**
77 	 * CTor
78 	 * Expect that every component is in range 0.0 .. 1.0
79 	 */
80 	this(float red, float green, float blue, float alpha = 1f) pure nothrow
81 	in {
82 		assert(red   >= 0f && red   <= 1f);
83 		assert(green >= 0f && green <= 1f);
84 		assert(blue  >= 0f && blue  <= 1f);
85 		assert(alpha >= 0f && alpha <= 1f);
86 	} body {
87 		this.red   = cast(ubyte)(ubyte.max * red);
88 		this.green = cast(ubyte)(ubyte.max * green);
89 		this.blue  = cast(ubyte)(ubyte.max * blue);
90 		this.alpha = cast(ubyte)(ubyte.max * alpha);
91 	}
92 	
93 //	debug(Dgame)
94 //	this(this) {
95 //		debug writeln("Postblit Color");
96 //	}
97 //	
98 //	debug(Dgame)
99 //	~this() {
100 //		debug writeln("DTor Color");
101 //	}
102 	
103 	/**
104 	 * Returns a copy of the current Color with a given transpareny.
105 	 * 
106 	 * Example:
107 	 * ----
108 	 * Color(current.red, current.green, current.blue, alpha);
109 	 * ----
110 	 */
111 	Color withTransparency(ubyte alpha = 0) const {
112 		return Color(this.red, this.green, this.blue, alpha);
113 	}
114 	
115 	/**
116 	 * Transfer the internal data to the SDL_Color
117 	 */
118 	void transferTo(SDL_Color* col) const pure nothrow
119 	in {
120 		assert(col !is null, "Cannot transfer anything to null.");
121 	} body {
122 		col.r = this.red;
123 		col.g = this.green;
124 		col.b = this.blue;
125 		col.a = this.alpha;
126 	}
127 	
128 	/**
129 	 * Set all color components to new values
130 	 */
131 	void set(ubyte red, ubyte green, ubyte blue, ubyte alpha = 255) pure nothrow {
132 		this.red   = red;
133 		this.green = green;
134 		this.blue  = blue;
135 		this.alpha = alpha;
136 	}
137 	
138 	/**
139 	 * Set all color components to new values
140 	 * Expect that every component is in range 0.0 .. 1.0
141 	 */
142 	void set(float red, float green, float blue, float alpha = 1f) pure nothrow
143 	in {
144 		assert(red   >= 0f && red   <= 1f);
145 		assert(green >= 0f && green <= 1f);
146 		assert(blue  >= 0f && blue  <= 1f);
147 		assert(alpha >= 0f && alpha <= 1f);
148 	} body {
149 		this.red   = cast(ubyte)(ubyte.max * red);
150 		this.green = cast(ubyte)(ubyte.max * green);
151 		this.blue  = cast(ubyte)(ubyte.max * blue);
152 		this.alpha = cast(ubyte)(ubyte.max * alpha);
153 	}
154 	
155 	/**
156 	 * opEquals: compares two Colors.
157 	 */
158 	bool opEquals(ref const Color col) const pure nothrow {
159 		return this.red == col.red && this.green == col.green
160 			&& this.blue == col.blue && this.alpha == col.alpha;
161 	}
162 	
163 	/**
164 	 * Returns a static float array with all color components.
165 	 * Every component is converted into OpenGL style.
166 	 * Means every component is in range 0.0 .. 1.0
167 	 */
168 	float[4] asGLColor() const pure nothrow {
169 		return [this.red   > 1 ? this.red   / 255f : this.red,
170 			this.green > 1 ? this.green / 255f : this.green,
171 			this.blue  > 1 ? this.blue  / 255f : this.blue,
172 			this.alpha > 1 ? this.alpha / 255f : this.alpha];
173 	}
174 	
175 	/**
176 	 * Returns the RGBA color information as static array
177 	 */
178 	ubyte[4] asRGBA() const pure nothrow {
179 		return [this.red, this.green, this.blue, this.alpha];
180 	}
181 	
182 	/**
183 	 * Returns RGB the color information as static array
184 	 */
185 	ubyte[3] asRGB() const pure nothrow {
186 		return [this.red, this.green, this.blue];
187 	}
188 }