ScummVM API documentation
blit-alpha.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "graphics/blit.h"
23 
24 namespace Graphics {
25 
27  friend class BlendBlit;
28 protected:
29 
30 template<bool rgbmod, bool alphamod>
31 struct BaseBlend {
32 public:
33  constexpr BaseBlend(const uint32 color) :
34  ca(alphamod ? ((color >> BlendBlit::kAModShift) & 0xFF) : 255),
35  cr(rgbmod ? ((color >> BlendBlit::kRModShift) & 0xFF) : 255),
36  cg(rgbmod ? ((color >> BlendBlit::kGModShift) & 0xFF) : 255),
37  cb(rgbmod ? ((color >> BlendBlit::kBModShift) & 0xFF) : 255) {}
38 
39 protected:
40  const byte ca, cr, cg, cb;
41 };
42 
43 template<bool rgbmod, bool alphamod>
44 struct AlphaBlend : public BaseBlend<rgbmod, alphamod> {
45 public:
46  constexpr AlphaBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
47 
48  inline void normal(const byte *in, byte *out) const {
49  uint32 ina;
50 
51  if (alphamod) {
52  ina = in[BlendBlit::kAIndex] * this->ca >> 8;
53  } else {
54  ina = in[BlendBlit::kAIndex];
55  }
56 
57  if (ina == 255) {
58  if (rgbmod) {
59  out[BlendBlit::kAIndex] = 255;
60  out[BlendBlit::kBIndex] = (in[BlendBlit::kBIndex] * this->cb >> 8);
61  out[BlendBlit::kGIndex] = (in[BlendBlit::kGIndex] * this->cg >> 8);
62  out[BlendBlit::kRIndex] = (in[BlendBlit::kRIndex] * this->cr >> 8);
63  } else {
64  out[BlendBlit::kAIndex] = 255;
65  out[BlendBlit::kBIndex] = in[BlendBlit::kBIndex];
66  out[BlendBlit::kGIndex] = in[BlendBlit::kGIndex];
67  out[BlendBlit::kRIndex] = in[BlendBlit::kRIndex];
68  }
69  } else if (ina != 0) {
70  if (rgbmod) {
71  const uint outb = (out[BlendBlit::kBIndex] * (255 - ina) >> 8);
72  const uint outg = (out[BlendBlit::kGIndex] * (255 - ina) >> 8);
73  const uint outr = (out[BlendBlit::kRIndex] * (255 - ina) >> 8);
74 
75  out[BlendBlit::kAIndex] = 255;
76  out[BlendBlit::kBIndex] = outb + (in[BlendBlit::kBIndex] * ina * this->cb >> 16);
77  out[BlendBlit::kGIndex] = outg + (in[BlendBlit::kGIndex] * ina * this->cg >> 16);
78  out[BlendBlit::kRIndex] = outr + (in[BlendBlit::kRIndex] * ina * this->cr >> 16);
79  } else {
80  out[BlendBlit::kAIndex] = 255;
81  out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * (255 - ina) + in[BlendBlit::kBIndex] * ina) >> 8;
82  out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * (255 - ina) + in[BlendBlit::kGIndex] * ina) >> 8;
83  out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * (255 - ina) + in[BlendBlit::kRIndex] * ina) >> 8;
84  }
85  }
86 
87  }
88 
89  inline void fill(byte *out) const {
90  uint32 ina = this->ca;
91 
92  /* if (ina == 255) {
93  if (rgbmod) {
94  out[BlendBlit::kAIndex] = 255;
95  out[BlendBlit::kBIndex] = this->cb;
96  out[BlendBlit::kGIndex] = this->cg;
97  out[BlendBlit::kRIndex] = this->cr;
98  } else {
99  out[BlendBlit::kAIndex] = 255;
100  out[BlendBlit::kBIndex] = 255;
101  out[BlendBlit::kGIndex] = 255;
102  out[BlendBlit::kRIndex] = 255;
103  }
104  } else if (ina != 0) */ {
105  if (rgbmod) {
106  const uint outb = (out[BlendBlit::kBIndex] * (255 - ina) >> 8);
107  const uint outg = (out[BlendBlit::kGIndex] * (255 - ina) >> 8);
108  const uint outr = (out[BlendBlit::kRIndex] * (255 - ina) >> 8);
109 
110  out[BlendBlit::kAIndex] = 255;
111  out[BlendBlit::kBIndex] = outb + (255 * ina * this->cb >> 16);
112  out[BlendBlit::kGIndex] = outg + (255 * ina * this->cg >> 16);
113  out[BlendBlit::kRIndex] = outr + (255 * ina * this->cr >> 16);
114  } else {
115  out[BlendBlit::kAIndex] = 255;
116  out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * (255 - ina) + 255 * ina) >> 8;
117  out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * (255 - ina) + 255 * ina) >> 8;
118  out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * (255 - ina) + 255 * ina) >> 8;
119  }
120  }
121 
122  }
123 };
124 
125 template<bool rgbmod, bool alphamod>
126 struct MultiplyBlend : public BaseBlend<rgbmod, alphamod> {
127 public:
128  constexpr MultiplyBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
129 
130  inline void normal(const byte *in, byte *out) const {
131  uint32 ina;
132 
133  if (alphamod) {
134  ina = in[BlendBlit::kAIndex] * this->ca >> 8;
135  } else {
136  ina = in[BlendBlit::kAIndex];
137  }
138 
139  if (ina == 255) {
140  if (rgbmod) {
141  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * this->cb) >> 8) >> 8;
142  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * this->cg) >> 8) >> 8;
143  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * this->cr) >> 8) >> 8;
144  } else {
145  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * in[BlendBlit::kBIndex] >> 8;
146  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * in[BlendBlit::kGIndex] >> 8;
147  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * in[BlendBlit::kRIndex] >> 8;
148  }
149  } else if (ina != 0) {
150  if (rgbmod) {
151  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * this->cb * ina) >> 16) >> 8;
152  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * this->cg * ina) >> 16) >> 8;
153  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * this->cr * ina) >> 16) >> 8;
154  } else {
155  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * ina) >> 8) >> 8;
156  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * ina) >> 8) >> 8;
157  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * ina) >> 8) >> 8;
158  }
159  }
160  }
161 
162  inline void fill(byte *out) const {
163  uint32 ina = this->ca;
164 
165  if (ina == 255) {
166  if (rgbmod) {
167  out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * this->cb) >> 8;
168  out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * this->cg) >> 8;
169  out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * this->cr) >> 8;
170  }
171  } else if (ina != 0) {
172  if (rgbmod) {
173  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((this->cb * ina) >> 8) >> 8;
174  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((this->cg * ina) >> 8) >> 8;
175  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((this->cr * ina) >> 8) >> 8;
176  } else {
177  out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * ina) >> 8;
178  out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * ina) >> 8;
179  out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * ina) >> 8;
180  }
181  }
182  }
183 };
184 
185 template<bool rgbmod, bool alphamod>
186 struct OpaqueBlend : public BaseBlend<rgbmod, alphamod> {
187 public:
188  constexpr OpaqueBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
189 
190  inline void normal(const byte *in, byte *out) const {
191  *(uint32 *)out = *(const uint32 *)in | BlendBlit::kAModMask;
192  }
193 };
194 
195 template<bool rgbmod, bool alphamod>
196 struct BinaryBlend : public BaseBlend<rgbmod, alphamod> {
197 public:
198  constexpr BinaryBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
199 
200  inline void normal(const byte *in, byte *out) const {
201  uint32 pix = *(const uint32 *)in;
202  uint32 a = pix & BlendBlit::kAModMask;
203 
204  if (a != 0) { // Full opacity (Any value not exactly 0 is Opaque here)
205  *(uint32 *)out = pix | BlendBlit::kAModMask;
206  }
207  }
208 };
209 
210 template<bool rgbmod, bool alphamod>
211 struct AdditiveBlend : public BaseBlend<rgbmod, alphamod> {
212 public:
213  constexpr AdditiveBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
214 
215  inline void normal(const byte *in, byte *out) const {
216  uint32 ina;
217 
218  if (alphamod) {
219  ina = in[BlendBlit::kAIndex] * this->ca >> 8;
220  } else {
221  ina = in[BlendBlit::kAIndex];
222  }
223 
224  if (ina == 255) {
225  if (rgbmod) {
226  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * this->cb) >> 8);
227  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * this->cg) >> 8);
228  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * this->cr) >> 8);
229  } else {
230  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + in[BlendBlit::kBIndex];
231  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + in[BlendBlit::kGIndex];
232  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + in[BlendBlit::kRIndex];
233  }
234  } else if (ina != 0) {
235  if (rgbmod) {
236  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * this->cb * ina) >> 16);
237  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * this->cg * ina) >> 16);
238  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * this->cr * ina) >> 16);
239  } else {
240  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * ina) >> 8);
241  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * ina) >> 8);
242  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * ina) >> 8);
243  }
244  }
245  }
246 
247  inline void fill(byte *out) const {
248  uint32 ina = this->ca;
249 
250  if (ina == 255) {
251  if (rgbmod) {
252  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + this->cb;
253  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + this->cg;
254  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + this->cr;
255  } else {
256  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + 255;
257  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + 255;
258  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + 255;
259  }
260  } else if (ina != 0) {
261  if (rgbmod) {
262  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((this->cb * ina) >> 8);
263  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((this->cg * ina) >> 8);
264  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((this->cr * ina) >> 8);
265  } else {
266  out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ina;
267  out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ina;
268  out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ina;
269  }
270  }
271  }
272 };
273 
274 template<bool rgbmod, bool alphamod>
275 struct SubtractiveBlend : public BaseBlend<rgbmod, alphamod> {
276 public:
277  constexpr SubtractiveBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
278 
279  inline void normal(const byte *in, byte *out) const {
280  uint32 ina = in[BlendBlit::kAIndex];
281  out[BlendBlit::kAIndex] = 255;
282 
283  if (ina == 255) {
284  if (rgbmod) {
285  out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * this->cb * (out[BlendBlit::kBIndex])) >> 16), 0);
286  out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * this->cg * (out[BlendBlit::kGIndex])) >> 16), 0);
287  out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * this->cr * (out[BlendBlit::kRIndex])) >> 16), 0);
288  } else {
289  out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * (out[BlendBlit::kBIndex])) >> 8), 0);
290  out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * (out[BlendBlit::kGIndex])) >> 8), 0);
291  out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * (out[BlendBlit::kRIndex])) >> 8), 0);
292  }
293  } else if (ina != 0) {
294  if (rgbmod) {
295  out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * this->cb * (out[BlendBlit::kBIndex]) * ina) >> 24), 0);
296  out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * this->cg * (out[BlendBlit::kGIndex]) * ina) >> 24), 0);
297  out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * this->cr * (out[BlendBlit::kRIndex]) * ina) >> 24), 0);
298  } else {
299  out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * (out[BlendBlit::kBIndex]) * ina) >> 16), 0);
300  out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * (out[BlendBlit::kGIndex]) * ina) >> 16), 0);
301  out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * (out[BlendBlit::kRIndex]) * ina) >> 16), 0);
302  }
303  }
304  }
305 
306  inline void fill(byte *out) const {
307  out[BlendBlit::kAIndex] = 255;
308 
309  if (rgbmod) {
310  out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((this->cb * out[BlendBlit::kBIndex]) >> 8), 0);
311  out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((this->cg * out[BlendBlit::kGIndex]) >> 8), 0);
312  out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((this->cr * out[BlendBlit::kRIndex]) >> 8), 0);
313  } else {
314  out[BlendBlit::kBIndex] = 0;
315  out[BlendBlit::kGIndex] = 0;
316  out[BlendBlit::kRIndex] = 0;
317  }
318  }
319 };
320 
321 }; // End of class BlendBlitImpl_Base
322 
323 template<class T>
324 void BlendBlit::blitT(Args &args, const TSpriteBlendMode &blendMode, const AlphaType &alphaType) {
325  bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
326  bool alphamod = ((args.color & kAModMask) != kAModMask);
327  if (args.scaleX == SCALE_THRESHOLD && args.scaleY == SCALE_THRESHOLD) {
328  if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_OPAQUE) {
329  T::template blitInnerLoop<T::template OpaqueBlend, false, false, false>(args);
330  } else if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_BINARY) {
331  T::template blitInnerLoop<T::template BinaryBlend, false, false, false>(args);
332  } else {
333  if (blendMode == BLEND_ADDITIVE) {
334  if (rgbmod) {
335  if (alphamod) {
336  T::template blitInnerLoop<T::template AdditiveBlend, false, true, true>(args);
337  } else {
338  T::template blitInnerLoop<T::template AdditiveBlend, false, true, false>(args);
339  }
340  } else {
341  if (alphamod) {
342  T::template blitInnerLoop<T::template AdditiveBlend, false, false, true>(args);
343  } else {
344  T::template blitInnerLoop<T::template AdditiveBlend, false, false, false>(args);
345  }
346  }
347  } else if (blendMode == BLEND_SUBTRACTIVE) {
348  if (rgbmod) {
349  T::template blitInnerLoop<T::template SubtractiveBlend, false, true, false>(args);
350  } else {
351  T::template blitInnerLoop<T::template SubtractiveBlend, false, false, false>(args);
352  }
353  } else if (blendMode == BLEND_MULTIPLY) {
354  if (rgbmod) {
355  if (alphamod) {
356  T::template blitInnerLoop<T::template MultiplyBlend, false, true, true>(args);
357  } else {
358  T::template blitInnerLoop<T::template MultiplyBlend, false, true, false>(args);
359  }
360  } else {
361  if (alphamod) {
362  T::template blitInnerLoop<T::template MultiplyBlend, false, false, true>(args);
363  } else {
364  T::template blitInnerLoop<T::template MultiplyBlend, false, false, false>(args);
365  }
366  }
367  } else {
368  assert(blendMode == BLEND_NORMAL);
369  if (rgbmod) {
370  if (alphamod) {
371  T::template blitInnerLoop<T::template AlphaBlend, false, true, true>(args);
372  } else {
373  T::template blitInnerLoop<T::template AlphaBlend, false, true, false>(args);
374  }
375  } else {
376  if (alphamod) {
377  T::template blitInnerLoop<T::template AlphaBlend, false, false, true>(args);
378  } else {
379  T::template blitInnerLoop<T::template AlphaBlend, false, false, false>(args);
380  }
381  }
382  }
383  }
384  } else {
385  if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_OPAQUE) {
386  T::template blitInnerLoop<T::template OpaqueBlend, true, false, false>(args);
387  } else if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_BINARY) {
388  T::template blitInnerLoop<T::template BinaryBlend, true, false, false>(args);
389  } else {
390  if (blendMode == BLEND_ADDITIVE) {
391  if (rgbmod) {
392  if (alphamod) {
393  T::template blitInnerLoop<T::template AdditiveBlend, true, true, true>(args);
394  } else {
395  T::template blitInnerLoop<T::template AdditiveBlend, true, true, false>(args);
396  }
397  } else {
398  if (alphamod) {
399  T::template blitInnerLoop<T::template AdditiveBlend, true, false, true>(args);
400  } else {
401  T::template blitInnerLoop<T::template AdditiveBlend, true, false, false>(args);
402  }
403  }
404  } else if (blendMode == BLEND_SUBTRACTIVE) {
405  if (rgbmod) {
406  T::template blitInnerLoop<T::template SubtractiveBlend, true, true, false>(args);
407  } else {
408  T::template blitInnerLoop<T::template SubtractiveBlend, true, false, false>(args);
409  }
410  } else if (blendMode == BLEND_MULTIPLY) {
411  if (rgbmod) {
412  if (alphamod) {
413  T::template blitInnerLoop<T::template MultiplyBlend, true, true, true>(args);
414  } else {
415  T::template blitInnerLoop<T::template MultiplyBlend, true, true, false>(args);
416  }
417  } else {
418  if (alphamod) {
419  T::template blitInnerLoop<T::template MultiplyBlend, true, false, true>(args);
420  } else {
421  T::template blitInnerLoop<T::template MultiplyBlend, true, false, false>(args);
422  }
423  }
424  } else {
425  assert(blendMode == BLEND_NORMAL);
426  if (rgbmod) {
427  if (alphamod) {
428  T::template blitInnerLoop<T::template AlphaBlend, true, true, true>(args);
429  } else {
430  T::template blitInnerLoop<T::template AlphaBlend, true, true, false>(args);
431  }
432  } else {
433  if (alphamod) {
434  T::template blitInnerLoop<T::template AlphaBlend, true, false, true>(args);
435  } else {
436  T::template blitInnerLoop<T::template AlphaBlend, true, false, false>(args);
437  }
438  }
439  }
440  }
441  }
442 }
443 
444 template<class T>
445 void BlendBlit::fillT(Args &args, const TSpriteBlendMode &blendMode) {
446  bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
447  bool alphamod = ((args.color & kAModMask) != kAModMask);
448 
449  if (blendMode == BLEND_ADDITIVE) {
450  if (rgbmod) {
451  if (alphamod) {
452  T::template fillInnerLoop<T::template AdditiveBlend, true, true>(args);
453  } else {
454  T::template fillInnerLoop<T::template AdditiveBlend, true, false>(args);
455  }
456  } else {
457  if (alphamod) {
458  T::template fillInnerLoop<T::template AdditiveBlend, false, true>(args);
459  } else {
460  T::template fillInnerLoop<T::template AdditiveBlend, false, false>(args);
461  }
462  }
463  } else if (blendMode == BLEND_SUBTRACTIVE) {
464  if (rgbmod) {
465  T::template fillInnerLoop<T::template SubtractiveBlend, true, false>(args);
466  } else {
467  T::template fillInnerLoop<T::template SubtractiveBlend, false, false>(args);
468  }
469  } else if (blendMode == BLEND_MULTIPLY) {
470  if (rgbmod) {
471  if (alphamod) {
472  T::template fillInnerLoop<T::template MultiplyBlend, true, true>(args);
473  } else {
474  T::template fillInnerLoop<T::template MultiplyBlend, true, false>(args);
475  }
476  } else {
477  if (alphamod) {
478  T::template fillInnerLoop<T::template MultiplyBlend, false, true>(args);
479  } else {
480  T::template fillInnerLoop<T::template MultiplyBlend, false, false>(args);
481  }
482  }
483  } else {
484  assert(blendMode == BLEND_NORMAL);
485  if (rgbmod) {
486  if (alphamod) {
487  T::template fillInnerLoop<T::template AlphaBlend, true, true>(args);
488  } else {
489  T::template fillInnerLoop<T::template AlphaBlend, true, false>(args);
490  }
491  } else {
492  if (alphamod) {
493  T::template fillInnerLoop<T::template AlphaBlend, false, true>(args);
494  } else {
495  T::template fillInnerLoop<T::template AlphaBlend, false, false>(args);
496  }
497  }
498  }
499 }
500 
501 } // End of namespace Graphics
Definition: blit-alpha.h:44
Definition: blit-alpha.h:196
Definition: formatinfo.h:28
Definition: blit.h:285
signed char * fill(signed char *first, signed char *last, Value val)
Definition: algorithm.h:168
Definition: blit-alpha.h:31
Definition: blit-alpha.h:186
Definition: blit-alpha.h:26