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.Graphic.Color;
25 
26 private:
27 
28 import derelict.sdl2.types;
29 
30 package(Dgame):
31 
32 @nogc
33 SDL_Color* _transfer(ref const Color4b src, ref SDL_Color dst) pure nothrow {
34     dst.r = src.red;
35     dst.g = src.green;
36     dst.b = src.blue;
37     dst.a = src.alpha;
38 
39     return &dst;
40 }
41 
42 public:
43 
44 /**
45  * Color4b defines a structure which contains 4 ubyte values, each for red, green, blue and alpha.
46  *
47  * Author: Randy Schuett (rswhite4@googlemail.com)
48  */
49 struct Color4b {
50     static immutable Color4b Black   = Color4b(0,     0,   0); /// Black Color (0, 0, 0)
51     static immutable Color4b White   = Color4b(255, 255, 255); /// White Color (255, 255, 255)
52     static immutable Color4b Red     = Color4b(255,   0,   0); /// Red Color (255, 0, 0)
53     static immutable Color4b Green   = Color4b(0,   255,   0); /// Green Color (0, 255, 0)
54     static immutable Color4b Blue    = Color4b(0,     0, 255); /// Blue Color (0, 0, 255)
55     static immutable Color4b Cyan    = Color4b(0,   255, 255); /// Cyan Color (0, 255, 255)
56     static immutable Color4b Yellow  = Color4b(255, 255,   0); /// Yellow Color (255, 255, 0)
57     static immutable Color4b Magenta = Color4b(255,   0, 255); /// Magenta Color (255, 0, 255)
58     static immutable Color4b Gray    = Color4b(179, 179, 179); /// Gray Color (179, 179, 179)
59     
60     /**
61      * The color components
62      */
63     ubyte red, green, blue, alpha;
64     
65     /**
66      * CTor
67      */
68     @nogc
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      */
79     @nogc
80     this(uint hexValue) pure nothrow {
81         version (LittleEndian) {
82             this.alpha = (hexValue >> 24) & 0xff;
83             this.blue  = (hexValue >> 16) & 0xff;
84             this.green = (hexValue >>  8) & 0xff;
85             this.red   = hexValue & 0xff;
86         } else {
87             this.red   = (hexValue >> 24) & 0xff;
88             this.green = (hexValue >> 16) & 0xff;
89             this.blue  = (hexValue >>  8) & 0xff;
90             this.alpha = hexValue & 0xff;
91         }
92     }
93     
94     /**
95      * CTor
96      *
97      * Expect that every component is in range 0.0 .. 1.0
98      */
99     @nogc
100     this(ref const Color4f col) pure nothrow
101     in {
102         assert(col.red   >= 0f && col.red   <= 1f);
103         assert(col.green >= 0f && col.green <= 1f);
104         assert(col.blue  >= 0f && col.blue  <= 1f);
105         assert(col.alpha >= 0f && col.alpha <= 1f);
106     } body {
107         this.red   = cast(ubyte)(ubyte.max * col.red);
108         this.green = cast(ubyte)(ubyte.max * col.green);
109         this.blue  = cast(ubyte)(ubyte.max * col.blue);
110         this.alpha = cast(ubyte)(ubyte.max * col.alpha);
111     }
112 
113     /**
114      * Returns a copy of the current Color with a given transpareny.
115      */
116     @nogc
117     Color4b withTransparency(ubyte alpha) const pure nothrow {
118         return Color4b(this.red, this.green, this.blue, alpha);
119     }
120 
121     /**
122      * opEquals: compares two Colors.
123      */
124     @nogc
125     bool opEquals(ref const Color4b col) const pure nothrow {
126         return this.red   == col.red &&
127                this.green == col.green &&
128                this.blue  == col.blue &&
129                this.alpha == col.alpha;
130     }
131     
132     /**
133      * Returns the RGBA color information as static array
134      */
135     @nogc
136     ubyte[4] asRGBA() const pure nothrow {
137         return [this.red, this.green, this.blue, this.alpha];
138     }
139     
140     /**
141      * Returns RGB the color information as static array
142      */
143      @nogc
144     ubyte[3] asRGB() const pure nothrow {
145         return [this.red, this.green, this.blue];
146     }
147 
148     /**
149      * Returns the RGBA color information as hex value
150      */
151     @nogc
152     uint asHex() const pure nothrow {
153         version (LittleEndian)
154             return ((this.alpha & 0xff) << 24) + ((this.blue & 0xff) << 16) + ((this.green & 0xff) << 8) + (this.red & 0xff);
155         else
156             return ((this.red & 0xff) << 24) + ((this.green & 0xff) << 16) + ((this.blue & 0xff) << 8) + (this.alpha & 0xff);
157     }
158 }
159 
160 unittest {
161     const Color4b red_col = Color4b.Red;
162     immutable uint hex_red = red_col.asHex();
163 
164     assert(hex_red == 0xff0000ff);
165     assert(Color4b(hex_red) == red_col);
166 }
167 
168 /**
169  * Color4f defines a structure which contains 4 floats values, each for red, green, blue and alpha.
170  *
171  * Author: Randy Schuett (rswhite4@googlemail.com)
172  */
173 struct Color4f {
174     static immutable Color4f Black   = Color4f(0,     0,   0); /// Black Color (0, 0, 0)
175     static immutable Color4f White   = Color4f(255, 255, 255); /// White Color (255, 255, 255)
176     static immutable Color4f Red     = Color4f(255,   0,   0); /// Red Color (255, 0, 0)
177     static immutable Color4f Green   = Color4f(0,   255,   0); /// Green Color (0, 255, 0)
178     static immutable Color4f Blue    = Color4f(0,     0, 255); /// Blue Color (0, 0, 255)
179     static immutable Color4f Cyan    = Color4f(0,   255, 255); /// Cyan Color (0, 255, 255)
180     static immutable Color4f Yellow  = Color4f(255, 255,   0); /// Yellow Color (255, 255, 0)
181     static immutable Color4f Magenta = Color4f(255,   0, 255); /// Magenta Color (255, 0, 255)
182     static immutable Color4f Gray    = Color4f(179, 179, 179); /// Gray Color (179, 179, 179)
183     
184     /**
185      * The color components
186      */
187     float red, green, blue, alpha;
188     
189     /**
190      * CTor
191      */
192     @nogc
193     this(ubyte red, ubyte green, ubyte blue, ubyte alpha = 255) pure nothrow {
194         this.red   = red   > 0 ? red   / 255f : 0;
195         this.green = green > 0 ? green / 255f : 0;
196         this.blue  = blue  > 0 ? blue  / 255f : 0;
197         this.alpha = alpha > 0 ? alpha / 255f : 0;
198     }
199 
200     /**
201      * CTor
202      * Expect that every component is in range 0.0 .. 1.0
203      */
204     @nogc
205     this(float red, float green, float blue, float alpha = 1) pure nothrow
206     in {
207         assert(red   >= 0f && red   <= 1f);
208         assert(green >= 0f && green <= 1f);
209         assert(blue  >= 0f && blue  <= 1f);
210         assert(alpha >= 0f && alpha <= 1f);
211     } body {
212         this.red   = red;
213         this.green = green;
214         this.blue  = blue;
215         this.alpha = alpha;
216     }
217 
218     /**
219      * CTor
220      */
221     @nogc
222     this(ref const Color4b col) pure nothrow {
223         this(col.red, col.green, col.blue, col.alpha);
224     }
225 
226     /**
227      * opEquals: compares two Colors.
228      */
229     @nogc
230     bool opEquals(ref const Color4f col) const pure nothrow {
231         return this.red   == col.red &&
232                this.green == col.green &&
233                this.blue  == col.blue &&
234                this.alpha == col.alpha;
235     }
236     
237     /**
238      * Returns the RGBA color information as static array
239      */
240     @nogc
241     float[4] asRGBA() const pure nothrow {
242         return [this.red, this.green, this.blue, this.alpha];
243     }
244     
245     /**
246      * Returns RGB the color information as static array
247      */
248      @nogc
249     float[3] asRGB() const pure nothrow {
250         return [this.red, this.green, this.blue];
251     }
252 }