1 module rip.concepts.templates;
2 
3 private
4 {
5 	import std.meta : allSatisfy;
6 	import std.range;
7 	import std.traits : isIntegral, isFloatingPoint, Unqual;
8 
9 	import rip.concepts.color;
10 	import rip.concepts.surface;
11 }
12 
13 /++
14 +  	Check all types for arithmetic types
15 +	Params:
16 +		T... 		=	types
17 +/
18 template allArithmetic(T...)
19 	if (T.length >= 1)
20 {
21 	template isNumberType(T)
22 	{
23 		enum bool isNumberType = isIntegral!(Unqual!T) || isFloatingPoint!(Unqual!T);
24 
25 	}
26 
27 	enum bool allArithmetic = allSatisfy!(isNumberType, T);
28 }
29 
30 /++
31 +  	Check range for RGBColor elements
32 +	Params:
33 +		Range 		=	range
34 +/
35 template isPixelRange(Range)
36 {
37 	enum bool isPixelRange = is(ElementType!Range == RGBColor);
38 }
39 
40 /++
41 +  	Creates getter function in compile-time
42 +	Params:
43 +		propertyVariableName 		=	name of variable
44 +		propertyName 				=	name of function
45 +/
46 template addTypedGetter(string propertyVariableName, string propertyName)
47 {
48 	import std.string : format;
49 
50 	const char[] addTypedGetter = format(
51 		`
52 		@property
53 		{
54 			T %2$s(T)() const
55 			{
56 				alias typeof(return) returnType;
57 				return cast(returnType) %1$s;
58 			}
59 		}`,
60 		propertyVariableName,
61 		propertyName
62 		);
63 }
64 
65 
66 /++
67 +  	Creates binary image operation in compile-time
68 +	Params:
69 +		operationSign 		=	...
70 +		operationName 		=	...
71 +/
72 template addBinaryImageOperation(string operationSign, string operationName)
73 {
74 	import std.string : format;
75 
76 	const char[] addBinaryImageOperation = format(
77 		`auto %2$s(Surface lhs, Surface rhs)
78 		{
79 			assert(lhs.getWidth!ulong == rhs.getWidth!ulong);
80 			assert(lhs.getHeight!ulong == rhs.getHeight!ulong);
81 
82 			RGBColor[] pixels;
83 
84 			auto intermediateResult = zip(
85 				lhs.getPixelsRange,
86 				rhs.getPixelsRange
87 			);
88 
89 			foreach (pixel; intermediateResult)
90 			{
91 				pixels ~= pixel[0] %1$s pixel[1];
92 			}
93 
94 			return pixels.toSurface(
95 				lhs.getWidth!ulong,
96 				lhs.getHeight!ulong
97 			);
98 		}`,
99 		operationSign,
100 		operationName
101 		);
102 }