1 /++
2  + Authors: Avaxar <avaxar@nekkl.org>
3  + Copyright: Copyright © 2023, Avaxar
4  + License: $(LINK2 https://mit-license.org, MIT License)
5  +/
6 
7 module dsdl2.blend;
8 @safe:
9 
10 import bindbc.sdl;
11 import dsdl2.sdl;
12 
13 import std.format : format;
14 
15 static if (sdlSupport >= SDLSupport.v2_0_6) {
16     /++
17      + D enum that wraps `SDL_BlendOperation` (from SDL 2.0.6) defining blending operations
18      +/
19     enum BlendOperation {
20         /++
21          + Wraps `SDL_BLENDOPERATION_*` enumeration constants
22          +/
23         add = SDL_BLENDOPERATION_ADD,
24         subtract = SDL_BLENDOPERATION_SUBTRACT, /// ditto
25         revSubtract = SDL_BLENDOPERATION_REV_SUBTRACT, /// ditto
26         minimum = SDL_BLENDOPERATION_MINIMUM, /// ditto
27         maximum = SDL_BLENDOPERATION_MAXIMUM /// ditto
28     }
29 
30     /++
31      + D enum that wraps `SDL_BlendFactor` (from SDL 2.0.6) defining blending multipliers
32      +/
33     enum BlendFactor {
34         /++
35          + Wraps `SDL_BLENDFACTOR_*` enumeration constants
36          +/
37         zero = SDL_BLENDFACTOR_ZERO,
38         one = SDL_BLENDFACTOR_ONE, /// ditto
39         srcColor = SDL_BLENDFACTOR_SRC_COLOR, /// ditto
40         oneMinusSrcColor = SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR, /// ditto
41         srcAlpha = SDL_BLENDFACTOR_SRC_ALPHA, /// ditto
42         oneMinusSrcAlpha = SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, /// ditto
43         dstColor = SDL_BLENDFACTOR_DST_COLOR, /// ditto
44         oneMinusDstColor = SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR, /// ditto
45         dstAlpha = SDL_BLENDFACTOR_DST_ALPHA, /// ditto
46         oneMinusDstAlpha = SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA /// ditto
47     }
48 }
49 
50 /++
51  + D struct that wraps `SDL_BlendMode` defining how blending should be done when an image is drawn on top of
52  + another
53  +/
54 struct BlendMode {
55     /++
56      + Preexisting built-in `dsdl2.BlendMode`s from `SDL_BLENDMODE_*` enumeration constants
57      +/
58     static immutable none = BlendMode(SDL_BLENDMODE_NONE);
59     static immutable blend = BlendMode(SDL_BLENDMODE_BLEND); /// ditto
60     static immutable add = BlendMode(SDL_BLENDMODE_ADD); /// ditto
61     static immutable mod = BlendMode(SDL_BLENDMODE_MOD); /// ditto
62     static if (sdlSupport >= SDLSupport.v2_0_12) {
63         static immutable mul = BlendMode(SDL_BLENDMODE_MUL); /// ditto
64     }
65 
66     SDL_BlendMode sdlBlendMode; /// Internal `SDL_BlendMode` enumeration
67 
68     this() @disable;
69 
70     /++
71      + Constructs a `dsdl2.BlendMode` from a vanilla `SDL_BlendMode` from bindbc-sdl
72      +
73      + Params:
74      +   sdlBlendMode = the `SDL_BlendMode` enumeration
75      +/
76     this(SDL_BlendMode sdlBlendMode) {
77         this.sdlBlendMode = sdlBlendMode;
78     }
79 
80     static if (sdlSupport >= SDLSupport.v2_0_6) {
81         /++
82          + Composes a custom `dsdl2.BlendMode` based on certain attributes for blending which wraps
83          + `SDL_ComposeCustomBlendMode` (from SDL 2.0.6)
84          +
85          + Params:
86          +   srcColorFactor = multipliers to the color components of the source
87          +   dstColorFactor = multipliers to the color components of the destination
88          +   colorOperation = operation to perform on the multiplied color components of the source and destination
89          +   srcAlphaFactor = multiplier to the alpha component of the source
90          +   dstAlphaFactor = multiplier to the color component of the destination
91          +   alphaOperation = operation to perform on the multiplied alpha components of the source and destination
92          + Throws: `dsdl2.SDLException` if impossible to compose the `dsdl2.BlendMode`
93          +/
94         this(BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation,
95             BlendFactor srcAlphaFactor, BlendFactor dstAlphaFactor, BlendOperation alphaOperation) @trusted
96         in {
97             assert(getVersion() >= Version(2, 0, 6));
98         }
99         do {
100 
101             this.sdlBlendMode = SDL_ComposeCustomBlendMode(srcColorFactor, dstColorFactor, colorOperation,
102                 srcAlphaFactor, dstAlphaFactor, alphaOperation);
103             if (this.sdlBlendMode != SDL_BLENDMODE_INVALID) {
104                 throw new SDLException("Invalid BlendMode composition", __FILE__, __LINE__);
105             }
106         }
107     }
108 
109     invariant {
110         static if (sdlSupport >= SDLSupport.v2_0_6) {
111             assert(this.sdlBlendMode != SDL_BLENDMODE_INVALID);
112         }
113     }
114 
115     /++
116      + Formats the `dsdl2.BlendMode` into its construction representation: `"dsdl2.Color(<sdlBlendMode>)"`
117      +
118      + Returns: the formatted `string`
119      +/
120     string toString() const {
121         return "dsdl2.BlendMode(%d)".format(this.sdlBlendMode);
122     }
123 }