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 }