1 module magicalrainbows.gradient;
2 
3 import magicalrainbows.formats;
4 import magicalrainbows.utils;
5 
6 struct Gradient {
7 	ulong index;
8 	ulong count;
9 	RGB888 start;
10 	RGB888 end;
11 	RGB888 front;
12 	void popFront() @safe pure {
13 		popFrontN(1);
14 	}
15 	void popFrontN(size_t steps) @safe pure {
16 		index += steps;
17 		double redInc = ((cast(double)end.red - cast(double)start.red) / cast(double)(count-1));
18 		double greenInc = ((cast(double)end.green - cast(double)start.green) / cast(double)(count-1));
19 		double blueInc = ((cast(double)end.blue - cast(double)start.blue) / cast(double)(count-1));
20 		front.red = cast(ubyte)(start.red + redInc * index);
21 		front.green = cast(ubyte)(start.green + greenInc * index);
22 		front.blue = cast(ubyte)(start.blue + blueInc * index);
23 	}
24 	bool empty() @safe pure {
25 		return index >= count;
26 	}
27 	this(T)(T from, T to, ulong steps) if(isColourFormat!T){
28 		count = steps;
29 		start = front = from.convert!RGB888;
30 		end = to.convert!RGB888;
31 	}
32 }
33 ///
34 @safe pure unittest {
35 	import std.algorithm;
36 	import std.range;
37 	bool closeEnough(Range1, Range2)(Range1 a, Range2 b) {
38 		bool similar(uint v, uint v2) {
39 			return !!v.among(v2 - 1, v2, v2 + 1);
40 		}
41 		foreach (pair; zip(a,b)) {
42 			if (!similar(pair[0].red, pair[1].red) || !similar(pair[0].green, pair[1].green) || !similar(pair[0].blue, pair[1].blue)) {
43 				return false;
44 			}
45 		}
46 		return true;
47 	}
48 	assert(closeEnough(Gradient(RGB888(255,0,0), RGB888(0,0,255), 20),
49 		only(
50 			RGB888(255, 0, 0),
51 			RGB888(241, 0, 13),
52 			RGB888(228, 0, 26),
53 			RGB888(214, 0, 40),
54 			RGB888(201, 0, 53),
55 			RGB888(187, 0, 67),
56 			RGB888(174, 0, 80),
57 			RGB888(161, 0, 93),
58 			RGB888(147, 0, 107),
59 			RGB888(134, 0, 120),
60 			RGB888(120, 0, 134),
61 			RGB888(107, 0, 147),
62 			RGB888(93, 0, 161),
63 			RGB888(80, 0, 174),
64 			RGB888(67, 0, 187),
65 			RGB888(53, 0, 201),
66 			RGB888(40, 0, 214),
67 			RGB888(26, 0, 228),
68 			RGB888(13, 0, 241),
69 			RGB888(0, 0, 254)
70 		)
71 	));
72 }