1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qglobal.h>
5
6#include "qdrawhelper_p.h"
7#include "qrgba64_p.h"
8#include "qrgbafloat.h"
9
10QT_BEGIN_NAMESPACE
11
12/* The constant alpha factor describes an alpha factor that gets applied
13 to the result of the composition operation combining it with the destination.
14
15 The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1.
16 we get the unmodified operation
17
18 result = src op dest
19 dest = result * const_alpha + dest * (1. - const_alpha)
20
21 This means that in the comments below, the first line is the const_alpha==255 case, the
22 second line the general one.
23
24 In the lines below:
25 s == src, sa == alpha(src), sia = 1 - alpha(src)
26 d == dest, da == alpha(dest), dia = 1 - alpha(dest)
27 ca = const_alpha, cia = 1 - const_alpha
28
29 The methods exist in two variants. One where we have a constant source, the other
30 where the source is an array of pixels.
31*/
32
33struct Argb32OperationsC
34{
35 typedef QRgb Type;
36 typedef quint8 Scalar;
37 typedef QRgb OptimalType;
38 typedef quint8 OptimalScalar;
39
40 static const Type clear;
41 static bool isOpaque(Type val)
42 { return qAlpha(rgb: val) == 255; }
43 static bool isTransparent(Type val)
44 { return qAlpha(rgb: val) == 0; }
45 static Scalar scalarFrom8bit(uint8_t a)
46 { return a; }
47 static void memfill(Type *ptr, Type value, qsizetype len)
48 { qt_memfill32(ptr, value, len); }
49 static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
50 { ::memcpy(dest: dest, src: src, n: len * sizeof(Type)); }
51
52 static OptimalType load(const Type *ptr)
53 { return *ptr; }
54 static OptimalType convert(const Type &val)
55 { return val; }
56 static void store(Type *ptr, OptimalType value)
57 { *ptr = value; }
58 static OptimalType add(OptimalType a, OptimalType b)
59 { return a + b; }
60 static OptimalScalar add(OptimalScalar a, OptimalScalar b)
61 { return a + b; }
62 static OptimalType plus(OptimalType a, OptimalType b)
63 { return comp_func_Plus_one_pixel(d: a, s: b); }
64 static OptimalScalar alpha(OptimalType val)
65 { return qAlpha(rgb: val); }
66 static OptimalScalar invAlpha(OptimalScalar c)
67 { return 255 - c; }
68 static OptimalScalar invAlpha(OptimalType val)
69 { return alpha(val: ~val); }
70 static OptimalScalar scalar(Scalar v)
71 { return v; }
72 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
73 { return BYTE_MUL(x: val, a); }
74 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
75 { return INTERPOLATE_PIXEL_255(x, a: a1, y, b: a2); }
76 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
77 { return BYTE_MUL(x: val, a); }
78 static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
79 { return qt_div_255(x: val * a); }
80 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
81 { return INTERPOLATE_PIXEL_255(x, a: a1, y, b: a2); }
82};
83
84const Argb32OperationsC::Type Argb32OperationsC::clear = 0;
85
86typedef Argb32OperationsC Argb32Operations;
87
88struct Rgba64OperationsBase
89{
90 typedef QRgba64 Type;
91 typedef quint16 Scalar;
92
93 static const Type clear;
94
95 static bool isOpaque(Type val)
96 { return val.isOpaque(); }
97 static bool isTransparent(Type val)
98 { return val.isTransparent(); }
99 static Scalar scalarFrom8bit(uint8_t a)
100 { return a * 257; }
101
102 static void memfill(Type *ptr, Type value, qsizetype len)
103 { qt_memfill64((quint64*)ptr, value, len); }
104 static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
105 { ::memcpy(dest: dest, src: src, n: len * sizeof(Type)); }
106};
107
108#if QT_CONFIG(raster_64bit)
109const Rgba64OperationsBase::Type Rgba64OperationsBase::clear = QRgba64::fromRgba64(c: 0);
110
111struct Rgba64OperationsC : public Rgba64OperationsBase
112{
113 typedef QRgba64 OptimalType;
114 typedef quint16 OptimalScalar;
115
116 static OptimalType load(const Type *ptr)
117 { return *ptr; }
118 static OptimalType convert(const Type &val)
119 { return val; }
120 static void store(Type *ptr, OptimalType value)
121 { *ptr = value; }
122 static OptimalType add(OptimalType a, OptimalType b)
123 { return QRgba64::fromRgba64(c: (quint64)a + (quint64)b); }
124 static OptimalScalar add(OptimalScalar a, OptimalScalar b)
125 { return a + b; }
126 static OptimalType plus(OptimalType a, OptimalType b)
127 { return addWithSaturation(a, b); }
128 static OptimalScalar alpha(OptimalType val)
129 { return val.alpha(); }
130 static OptimalScalar invAlpha(Scalar c)
131 { return 65535 - c; }
132 static OptimalScalar invAlpha(OptimalType val)
133 { return 65535 - alpha(val); }
134 static OptimalScalar scalar(Scalar v)
135 { return v; }
136 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
137 { return multiplyAlpha255(rgba64: val, alpha255: a); }
138 static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
139 { return qt_div_255(x: val * a); }
140 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
141 { return interpolate255(x, alpha1: a1, y, alpha2: a2); }
142 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
143 { return multiplyAlpha65535(rgba64: val, alpha65535: a); }
144 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
145 { return interpolate65535(x, alpha1: a1, y, alpha2: a2); }
146};
147
148#if defined(__SSE2__)
149struct Rgba64OperationsSSE2 : public Rgba64OperationsBase
150{
151 typedef __m128i OptimalType;
152 typedef __m128i OptimalScalar;
153
154 static OptimalType load(const Type *ptr)
155 {
156 return _mm_loadl_epi64(p: reinterpret_cast<const __m128i *>(ptr));
157 }
158 static OptimalType convert(const Type &value)
159 {
160#ifdef Q_PROCESSOR_X86_64
161 return _mm_cvtsi64_si128(a: value);
162#else
163 return load(&value);
164#endif
165 }
166 static void store(Type *ptr, OptimalType value)
167 {
168 _mm_storel_epi64(p: reinterpret_cast<__m128i *>(ptr), a: value);
169 }
170 static OptimalType add(OptimalType a, OptimalType b)
171 {
172 return _mm_add_epi16(a: a, b: b);
173 }
174// same as above:
175// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
176 static OptimalType plus(OptimalType a, OptimalType b)
177 {
178 return _mm_adds_epu16(a: a, b: b);
179 }
180 static OptimalScalar alpha(OptimalType c)
181 {
182 return _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3));
183 }
184 static OptimalScalar invAlpha(Scalar c)
185 {
186 return scalar(n: 65535 - c);
187 }
188 static OptimalScalar invAlpha(OptimalType c)
189 {
190 return _mm_xor_si128(a: _mm_set1_epi16(w: -1), b: alpha(c));
191 }
192 static OptimalScalar scalar(Scalar n)
193 {
194 return _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0));
195 }
196 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
197 {
198 return multiplyAlpha255(rgba64: val, alpha255: a);
199 }
200// same as above:
201// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
202 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
203 {
204 return interpolate255(x, alpha1: a1, y, alpha2: a2);
205 }
206 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
207 {
208 return multiplyAlpha65535(rgba64: val, va: a);
209 }
210 // a2 is const-ref because otherwise MSVC2015@x86 complains that it can't 16-byte align the argument.
211 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, const OptimalScalar &a2)
212 {
213 return interpolate65535(x, alpha1: a1, y, alpha2: a2);
214 }
215};
216#endif
217
218#if defined(__ARM_NEON__)
219struct Rgba64OperationsNEON : public Rgba64OperationsBase
220{
221 typedef uint16x4_t OptimalType;
222 typedef uint16x4_t OptimalScalar;
223
224 static OptimalType load(const Type *ptr)
225 {
226 return vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)));
227 }
228 static OptimalType convert(const Type &val)
229 {
230 return vreinterpret_u16_u64(vmov_n_u64(val));
231 }
232 static void store(Type *ptr, OptimalType value)
233 {
234 vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value));
235 }
236 static OptimalType add(OptimalType a, OptimalType b)
237 {
238 return vadd_u16(a, b);
239 }
240// same as above:
241// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
242 static OptimalType plus(OptimalType a, OptimalType b)
243 {
244 return vqadd_u16(a, b);
245 }
246 static OptimalScalar alpha(OptimalType c)
247 {
248 return vdup_lane_u16(c, 3);
249 }
250 static OptimalScalar invAlpha(Scalar c)
251 {
252 return scalar(65535 - c);
253 }
254 static OptimalScalar invAlpha(OptimalType c)
255 {
256 return vmvn_u16(alpha(c));
257 }
258 static OptimalScalar scalar(Scalar n)
259 {
260 return vdup_n_u16(n);
261 }
262 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
263 {
264 return multiplyAlpha255(val, a);
265 }
266// same as above:
267// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
268 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
269 {
270 return interpolate255(x, a1, y, a2);
271 }
272 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
273 {
274 return multiplyAlpha65535(val, a);
275 }
276 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
277 {
278 return interpolate65535(x, a1, y, a2);
279 }
280};
281#endif
282
283#if defined(__SSE2__)
284typedef Rgba64OperationsSSE2 Rgba64Operations;
285#elif defined(__ARM_NEON__)
286typedef Rgba64OperationsNEON Rgba64Operations;
287#else
288typedef Rgba64OperationsC Rgba64Operations;
289#endif
290
291#endif // QT_CONFIG(raster_64bit)
292
293#if QT_CONFIG(raster_fp)
294
295static inline QRgbaFloat32 qRgbaFloat32(float r, float g, float b, float a)
296{
297 return QRgbaFloat32{.r: r, .g: g, .b: b, .a: a};
298}
299
300struct RgbaFPOperationsBase
301{
302 typedef QRgbaFloat32 Type;
303 typedef float Scalar;
304
305 static inline constexpr Type clear = { .r: 0, .g: 0, .b: 0, .a: 0 };
306
307 static bool isOpaque(Type val)
308 { return val.a >= 1.0f; }
309 static bool isTransparent(Type val)
310 { return val.a <= 0.0f; }
311 static Scalar scalarFrom8bit(uint8_t a)
312 { return a * (1.0f / 255.0f); }
313
314 static void memfill(Type *ptr, Type value, qsizetype len)
315 {
316 for (qsizetype i = 0; i < len; ++i)
317 ptr[i] = value;
318 }
319 static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
320 { ::memcpy(dest: dest, src: src, n: len * sizeof(Type)); }
321};
322
323struct RgbaFPOperationsC : RgbaFPOperationsBase
324{
325 typedef QRgbaFloat32 OptimalType;
326 typedef float OptimalScalar;
327
328 static OptimalType load(const Type *ptr)
329 {
330 return QRgbaFloat32 { .r: ptr->r, .g: ptr->g, .b: ptr->b, .a: ptr->a };
331 }
332 static OptimalType convert(const Type &val)
333 {
334 return QRgbaFloat32 { .r: val.r, .g: val.g, .b: val.b, .a: val.a };
335 }
336 static void store(Type *ptr, OptimalType value)
337 {
338 ptr->r = value.r;
339 ptr->g = value.g;
340 ptr->b = value.b;
341 ptr->a = value.a;
342 }
343 static OptimalType add(OptimalType a, OptimalType b)
344 {
345 a.r += b.r;
346 a.g += b.g;
347 a.b += b.b;
348 a.a += b.a;
349 return a;
350 }
351 static OptimalScalar add(OptimalScalar a, OptimalScalar b)
352 { return a + b; }
353 static OptimalType plus(OptimalType a, OptimalType b)
354 {
355 a = add(a, b); // no saturation on color values
356 if (a.a < 0.0f) a.a = 0.0f;
357 else if (a.a > 1.0f) a.a = 1.0f;
358 return a;
359 }
360 static OptimalScalar alpha(OptimalType val)
361 { return val.a; }
362 static OptimalScalar invAlpha(OptimalScalar c)
363 { return 1.0f - c; }
364 static OptimalScalar invAlpha(OptimalType val)
365 { return 1.0f - val.a; }
366 static OptimalScalar scalar(Scalar v)
367 { return v; }
368 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
369 {
370 val.r *= a;
371 val.g *= a;
372 val.b *= a;
373 val.a *= a;
374 return val;
375 }
376 static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
377 {
378 return val * a * (1.0f / 255.0f);
379 }
380 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
381 {
382 return add(a: multiplyAlpha(val: x, a: a1), b: multiplyAlpha(val: y, a: a2));
383 }
384 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
385 {
386 return multiplyAlpha(val, a: a * (1.0f / 255.0f));
387 }
388 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
389 {
390 return add(a: multiplyAlpha8bit(val: x, a: a1), b: multiplyAlpha8bit(val: y, a: a2));
391 }
392};
393
394#if defined(__SSE2__)
395struct RgbaFPOperationsSSE2 : public RgbaFPOperationsBase
396{
397 typedef __m128 OptimalType;
398 typedef __m128 OptimalScalar;
399
400 static OptimalType load(const Type *ptr)
401 {
402 return _mm_load_ps(p: reinterpret_cast<const float *>(ptr));
403 }
404 static OptimalType convert(const Type &value)
405 {
406 return load(ptr: &value);
407 }
408 static void store(Type *ptr, OptimalType value)
409 {
410 _mm_store_ps(p: reinterpret_cast<float *>(ptr), a: value);
411 }
412 static OptimalType add(OptimalType a, OptimalType b)
413 {
414 return _mm_add_ps(a: a, b: b);
415 }
416// same as above:
417// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
418 static OptimalType plus(OptimalType a, OptimalType b)
419 {
420 a = _mm_add_ps(a: a, b: b);
421 __m128 aa = _mm_min_ps(a: a, b: _mm_set1_ps(w: 1.0f));
422 aa = _mm_max_ps(a: aa, b: _mm_set1_ps(w: 0.0f));
423 // An indirect insert using only SSE2:
424 aa = _mm_shuffle_ps(aa, a, _MM_SHUFFLE(2, 2, 3, 3));
425 a = _mm_shuffle_ps(a, aa, _MM_SHUFFLE(0, 2, 1, 0));
426 return a;
427 }
428 static OptimalScalar alpha(OptimalType c)
429 {
430 return _mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3));
431 }
432 static OptimalScalar invAlpha(Scalar c)
433 {
434 return _mm_set1_ps(w: 1.0f - float(c));
435 }
436 static OptimalScalar invAlpha(OptimalType c)
437 {
438 return _mm_sub_ps(a: _mm_set1_ps(w: 1.0f), b: alpha(c));
439 }
440 static OptimalScalar scalar(Scalar n)
441 {
442 return _mm_set1_ps(w: float(n));
443 }
444 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
445 {
446 return _mm_mul_ps(a: val, b: a);
447 }
448 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
449 {
450 return add(a: multiplyAlpha(val: x, a: a1), b: multiplyAlpha(val: y, a: a2));
451 }
452 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
453 {
454 return multiplyAlpha(val, a: _mm_set1_ps(w: a * (1.0f / 255.0f)));
455 }
456// same as above:
457// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
458 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
459 {
460 return add(a: multiplyAlpha8bit(val: x, a: a1), b: multiplyAlpha8bit(val: y, a: a2));
461 }
462};
463#endif
464
465#if defined(__SSE2__)
466typedef RgbaFPOperationsSSE2 RgbaFPOperations;
467#else
468typedef RgbaFPOperationsC RgbaFPOperations;
469#endif
470
471#endif // QT_CONFIG(raster_fp)
472
473/*
474 result = 0
475 d = d * cia
476*/
477template<class Ops>
478inline static void comp_func_Clear_template(typename Ops::Type *dest, int length, uint const_alpha)
479{
480 if (const_alpha == 255)
481 Ops::memfill(dest, Ops::clear, length);
482 else {
483 uint ialpha = 255 - const_alpha;
484 for (int i = 0; i < length; ++i) {
485 Ops::store(&dest[i], Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha));
486 }
487 }
488}
489
490void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
491{
492 comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
493}
494
495void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
496{
497 comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
498}
499
500#if QT_CONFIG(raster_64bit)
501void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
502{
503 comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
504}
505
506void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
507{
508 comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
509}
510#endif
511
512#if QT_CONFIG(raster_fp)
513void QT_FASTCALL comp_func_solid_Clear_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32, uint const_alpha)
514{
515 comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha);
516}
517
518void QT_FASTCALL comp_func_Clear_rgbafp(QRgbaFloat32 *dest, const QRgbaFloat32 *, int length, uint const_alpha)
519{
520 comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha);
521}
522#endif
523
524/*
525 result = s
526 dest = s * ca + d * cia
527*/
528template<class Ops>
529inline static void comp_func_solid_Source_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
530{
531 if (const_alpha == 255)
532 Ops::memfill(dest, color, length);
533 else {
534 const uint ialpha = 255 - const_alpha;
535 auto s = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
536 for (int i = 0; i < length; ++i) {
537 auto d = Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha);
538 Ops::store(&dest[i], Ops::add(s, d));
539 }
540 }
541}
542
543template<class Ops>
544inline static void comp_func_Source_template(typename Ops::Type *Q_DECL_RESTRICT dest,
545 const typename Ops::Type *Q_DECL_RESTRICT src,
546 int length, uint const_alpha)
547{
548 if (const_alpha == 255)
549 Ops::memcpy(dest, src, length);
550 else {
551 const uint ialpha = 255 - const_alpha;
552 for (int i = 0; i < length; ++i) {
553 auto s = Ops::load(src + i);
554 auto d = Ops::load(dest + i);
555 Ops::store(&dest[i], Ops::interpolate8bit(s, const_alpha, d, ialpha));
556 }
557 }
558}
559
560void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
561{
562 comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
563}
564
565void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
566{
567 comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
568}
569
570#if QT_CONFIG(raster_64bit)
571void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
572{
573 comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
574}
575
576void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
577{
578 comp_func_Source_template<Rgba64Operations>(dest, src, length, const_alpha);
579}
580#endif
581
582#if QT_CONFIG(raster_fp)
583void QT_FASTCALL comp_func_solid_Source_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
584{
585 comp_func_solid_Source_template<RgbaFPOperations>(dest, length, color, const_alpha);
586}
587
588void QT_FASTCALL comp_func_Source_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
589{
590 comp_func_Source_template<RgbaFPOperations>(dest, src, length, const_alpha);
591}
592#endif
593
594void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
595{
596}
597
598void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
599{
600}
601
602#if QT_CONFIG(raster_64bit)
603void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
604{
605}
606
607void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint)
608{
609}
610#endif
611
612#if QT_CONFIG(raster_fp)
613void QT_FASTCALL comp_func_solid_Destination_rgbafp(QRgbaFloat32 *, int, QRgbaFloat32, uint)
614{
615}
616
617void QT_FASTCALL comp_func_Destination_rgbafp(QRgbaFloat32 *, const QRgbaFloat32 *, int, uint)
618{
619}
620#endif
621
622/*
623 result = s + d * sia
624 dest = (s + d * sia) * ca + d * cia
625 = s * ca + d * (sia * ca + cia)
626 = s * ca + d * (1 - sa*ca)
627*/
628template<class Ops>
629inline static void comp_func_solid_SourceOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
630{
631 if (const_alpha == 255 && Ops::isOpaque(color))
632 Ops::memfill(dest, color, length);
633 else {
634 auto c = Ops::convert(color);
635 if (const_alpha != 255)
636 c = Ops::multiplyAlpha8bit(c, const_alpha);
637 auto cAlpha = Ops::invAlpha(c);
638 for (int i = 0; i < length; ++i) {
639 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), cAlpha);
640 Ops::store(&dest[i], Ops::add(c, d));
641 }
642 }
643}
644
645template<class Ops>
646inline static void comp_func_SourceOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
647 const typename Ops::Type *Q_DECL_RESTRICT src,
648 int length, uint const_alpha)
649{
650 if (const_alpha == 255) {
651 for (int i = 0; i < length; ++i) {
652 auto c = src[i];
653 if (Ops::isOpaque(c))
654 Ops::store(&dest[i], Ops::convert(c));
655 else if (!Ops::isTransparent(c)) {
656 auto s = Ops::convert(c);
657 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
658 Ops::store(&dest[i], Ops::add(s, d));
659 }
660 }
661 } else {
662 for (int i = 0; i < length; ++i) {
663 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
664 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
665 Ops::store(&dest[i], Ops::add(s, d));
666 }
667 }
668}
669
670void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
671{
672 comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
673}
674
675void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
676{
677 comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
678}
679
680#if QT_CONFIG(raster_64bit)
681void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
682{
683 comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
684}
685
686void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
687{
688 comp_func_SourceOver_template<Rgba64Operations>(dest, src, length, const_alpha);
689}
690#endif
691
692#if QT_CONFIG(raster_fp)
693void QT_FASTCALL comp_func_solid_SourceOver_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
694{
695 comp_func_solid_SourceOver_template<RgbaFPOperations>(dest, length, color, const_alpha);
696}
697
698
699void QT_FASTCALL comp_func_SourceOver_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
700{
701 comp_func_SourceOver_template<RgbaFPOperations>(dest, src, length, const_alpha);
702}
703#endif
704
705/*
706 result = d + s * dia
707 dest = (d + s * dia) * ca + d * cia
708 = d + s * dia * ca
709*/
710template<class Ops>
711inline static void comp_func_solid_DestinationOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
712{
713 auto c = Ops::convert(color);
714 if (const_alpha != 255)
715 c = Ops::multiplyAlpha8bit(c, const_alpha);
716 for (int i = 0; i < length; ++i) {
717 auto d = Ops::load(&dest[i]);
718 auto s = Ops::multiplyAlpha(c, Ops::invAlpha(d));
719 Ops::store(&dest[i], Ops::add(s, d));
720 }
721}
722
723template<class Ops>
724inline static void comp_func_DestinationOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
725 const typename Ops::Type *Q_DECL_RESTRICT src,
726 int length, uint const_alpha)
727{
728 if (const_alpha == 255) {
729 for (int i = 0; i < length; ++i) {
730 auto d = Ops::load(&dest[i]);
731 auto s = Ops::multiplyAlpha(Ops::load(&src[i]), Ops::invAlpha(d));
732 Ops::store(&dest[i], Ops::add(s, d));
733 }
734 } else {
735 for (int i = 0; i < length; ++i) {
736 auto d = Ops::load(&dest[i]);
737 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
738 s = Ops::multiplyAlpha(s, Ops::invAlpha(d));
739 Ops::store(&dest[i], Ops::add(s, d));
740 }
741 }
742}
743
744void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
745{
746 comp_func_solid_DestinationOver_template<Argb32Operations>(dest, length, color, const_alpha);
747}
748
749void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
750{
751 comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
752}
753
754#if QT_CONFIG(raster_64bit)
755void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
756{
757 comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
758}
759
760void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
761{
762 comp_func_DestinationOver_template<Rgba64Operations>(dest, src, length, const_alpha);
763}
764#endif
765
766#if QT_CONFIG(raster_fp)
767void QT_FASTCALL comp_func_solid_DestinationOver_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
768{
769 comp_func_solid_DestinationOver_template<RgbaFPOperations>(dest, length, color, const_alpha);
770}
771
772void QT_FASTCALL comp_func_DestinationOver_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
773{
774 comp_func_DestinationOver_template<RgbaFPOperations>(dest, src, length, const_alpha);
775}
776#endif
777
778/*
779 result = s * da
780 dest = s * da * ca + d * cia
781*/
782template<class Ops>
783inline static void comp_func_solid_SourceIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
784{
785 if (const_alpha == 255) {
786 auto c = Ops::convert(color);
787 for (int i = 0; i < length; ++i) {
788 Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::alpha(Ops::load(&dest[i]))));
789 }
790 } else {
791 auto c = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
792 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
793 for (int i = 0; i < length; ++i) {
794 auto d = Ops::load(&dest[i]);
795 Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, cia));
796 }
797 }
798}
799
800template<class Ops>
801inline static void comp_func_SourceIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
802 const typename Ops::Type *Q_DECL_RESTRICT src,
803 int length, uint const_alpha)
804{
805 if (const_alpha == 255) {
806 for (int i = 0; i < length; ++i) {
807 auto s = Ops::load(&src[i]);
808 Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::alpha(Ops::load(&dest[i]))));
809 }
810 } else {
811 auto ca = Ops::scalarFrom8bit(const_alpha);
812 auto cia = Ops::invAlpha(ca);
813 auto cav = Ops::scalar(ca);
814 for (int i = 0; i < length; ++i) {
815 auto d = Ops::load(&dest[i]);
816 auto s = Ops::multiplyAlpha(Ops::load(&src[i]), cav);
817 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, cia));
818 }
819 }
820}
821
822void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
823{
824 comp_func_solid_SourceIn_template<Argb32Operations>(dest, length, color, const_alpha);
825}
826
827void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
828{
829 comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
830}
831
832#if QT_CONFIG(raster_64bit)
833void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
834{
835 comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
836}
837
838void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
839{
840 comp_func_SourceIn_template<Rgba64Operations>(dest, src, length, const_alpha);
841}
842#endif
843
844#if QT_CONFIG(raster_fp)
845void QT_FASTCALL comp_func_solid_SourceIn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
846{
847 comp_func_solid_SourceIn_template<RgbaFPOperations>(dest, length, color, const_alpha);
848}
849
850void QT_FASTCALL comp_func_SourceIn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
851{
852 comp_func_SourceIn_template<RgbaFPOperations>(dest, src, length, const_alpha);
853}
854#endif
855
856/*
857 result = d * sa
858 dest = d * sa * ca + d * cia
859 = d * (sa * ca + cia)
860*/
861template<class Ops>
862inline static void comp_func_solid_DestinationIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
863{
864 auto sa = Ops::alpha(Ops::convert(color));
865 if (const_alpha != 255) {
866 sa = Ops::multiplyAlpha8bit(sa, const_alpha);
867 sa = Ops::add(sa, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
868 }
869
870 for (int i = 0; i < length; ++i) {
871 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
872 }
873}
874
875template<class Ops>
876inline static void comp_func_DestinationIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
877 const typename Ops::Type *Q_DECL_RESTRICT src,
878 int length, uint const_alpha)
879{
880 if (const_alpha == 255) {
881 for (int i = 0; i < length; ++i) {
882 auto a = Ops::alpha(Ops::load(&src[i]));
883 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), a));
884 }
885 } else {
886 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
887 for (int i = 0; i < length; ++i) {
888 auto sa = Ops::multiplyAlpha8bit(Ops::alpha(Ops::load(&src[i])), const_alpha);
889 sa = Ops::add(sa, cia);
890 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
891 }
892 }
893}
894
895void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
896{
897 comp_func_solid_DestinationIn_template<Argb32Operations>(dest, length, color, const_alpha);
898}
899
900void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
901{
902 comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
903}
904
905#if QT_CONFIG(raster_64bit)
906void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
907{
908 comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
909}
910
911void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
912{
913 comp_func_DestinationIn_template<Rgba64Operations>(dest, src, length, const_alpha);
914}
915#endif
916
917#if QT_CONFIG(raster_fp)
918void QT_FASTCALL comp_func_solid_DestinationIn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
919{
920 comp_func_solid_DestinationIn_template<RgbaFPOperations>(dest, length, color, const_alpha);
921}
922
923void QT_FASTCALL comp_func_DestinationIn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
924{
925 comp_func_DestinationIn_template<RgbaFPOperations>(dest, src, length, const_alpha);
926}
927#endif
928
929/*
930 result = s * dia
931 dest = s * dia * ca + d * cia
932*/
933template<class Ops>
934inline static void comp_func_solid_SourceOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
935{
936 auto c = Ops::convert(color);
937 if (const_alpha == 255) {
938 for (int i = 0; i < length; ++i)
939 Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::invAlpha(Ops::load(&dest[i]))));
940 } else {
941 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
942 c = Ops::multiplyAlpha8bit(c, const_alpha);
943 for (int i = 0; i < length; ++i) {
944 auto d = Ops::load(&dest[i]);
945 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, cia));
946 }
947 }
948}
949
950template<class Ops>
951inline static void comp_func_SourceOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
952 const typename Ops::Type *Q_DECL_RESTRICT src,
953 int length, uint const_alpha)
954{
955 if (const_alpha == 255) {
956 for (int i = 0; i < length; ++i) {
957 auto s = Ops::load(&src[i]);
958 auto d = Ops::load(&dest[i]);
959 Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::invAlpha(d)));
960 }
961 } else {
962 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
963 for (int i = 0; i < length; ++i) {
964 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
965 auto d = Ops::load(&dest[i]);
966 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, cia));
967 }
968 }
969}
970
971void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
972{
973 comp_func_solid_SourceOut_template<Argb32Operations>(dest, length, color, const_alpha);
974}
975
976void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
977{
978 comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
979}
980
981#if QT_CONFIG(raster_64bit)
982void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
983{
984 comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
985}
986
987void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
988{
989 comp_func_SourceOut_template<Rgba64Operations>(dest, src, length, const_alpha);
990}
991#endif
992
993#if QT_CONFIG(raster_fp)
994void QT_FASTCALL comp_func_solid_SourceOut_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
995{
996 comp_func_solid_SourceOut_template<RgbaFPOperations>(dest, length, color, const_alpha);
997}
998
999void QT_FASTCALL comp_func_SourceOut_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1000{
1001 comp_func_SourceOut_template<RgbaFPOperations>(dest, src, length, const_alpha);
1002}
1003#endif
1004
1005/*
1006 result = d * sia
1007 dest = d * sia * ca + d * cia
1008 = d * (sia * ca + cia)
1009*/
1010template<class Ops>
1011inline static void comp_func_solid_DestinationOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1012{
1013 auto sai = Ops::invAlpha(Ops::convert(color));
1014 if (const_alpha != 255) {
1015 sai = Ops::multiplyAlpha8bit(sai, const_alpha);
1016 sai = Ops::add(sai, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
1017 }
1018
1019 for (int i = 0; i < length; ++i) {
1020 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sai));
1021 }
1022}
1023
1024template<class Ops>
1025inline static void comp_func_DestinationOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1026 const typename Ops::Type *Q_DECL_RESTRICT src,
1027 int length, uint const_alpha)
1028{
1029 if (const_alpha == 255) {
1030 for (int i = 0; i < length; ++i) {
1031 auto sia = Ops::invAlpha(Ops::load(&src[i]));
1032 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
1033 }
1034 } else {
1035 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
1036 for (int i = 0; i < length; ++i) {
1037 auto sia = Ops::multiplyAlpha8bit(Ops::invAlpha(Ops::load(&src[i])), const_alpha);
1038 sia = Ops::add(sia, cia);
1039 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
1040 }
1041 }
1042}
1043
1044void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
1045{
1046 comp_func_solid_DestinationOut_template<Argb32Operations>(dest, length, color, const_alpha);
1047}
1048
1049void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1050{
1051 comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
1052}
1053
1054#if QT_CONFIG(raster_64bit)
1055void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1056{
1057 comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
1058}
1059
1060void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1061{
1062 comp_func_DestinationOut_template<Rgba64Operations>(dest, src, length, const_alpha);
1063}
1064#endif
1065
1066#if QT_CONFIG(raster_fp)
1067void QT_FASTCALL comp_func_solid_DestinationOut_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1068{
1069 comp_func_solid_DestinationOut_template<RgbaFPOperations>(dest, length, color, const_alpha);
1070}
1071
1072void QT_FASTCALL comp_func_DestinationOut_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1073{
1074 comp_func_DestinationOut_template<RgbaFPOperations>(dest, src, length, const_alpha);
1075}
1076#endif
1077
1078/*
1079 result = s*da + d*sia
1080 dest = s*da*ca + d*sia*ca + d *cia
1081 = s*ca * da + d * (sia*ca + cia)
1082 = s*ca * da + d * (1 - sa*ca)
1083*/
1084template<class Ops>
1085inline static void comp_func_solid_SourceAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1086{
1087 auto c = Ops::convert(color);
1088 if (const_alpha != 255)
1089 c = Ops::multiplyAlpha8bit(c, const_alpha);
1090 auto sia = Ops::invAlpha(c);
1091 for (int i = 0; i < length; ++i) {
1092 auto d = Ops::load(&dest[i]);
1093 Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, sia));
1094 }
1095}
1096
1097template<class Ops>
1098inline static void comp_func_SourceAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1099 const typename Ops::Type *Q_DECL_RESTRICT src,
1100 int length, uint const_alpha)
1101{
1102 if (const_alpha == 255) {
1103 for (int i = 0; i < length; ++i) {
1104 auto s = Ops::load(&src[i]);
1105 auto d = Ops::load(&dest[i]);
1106 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
1107 }
1108 } else {
1109 for (int i = 0; i < length; ++i) {
1110 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
1111 auto d = Ops::load(&dest[i]);
1112 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
1113 }
1114 }
1115}
1116
1117void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
1118{
1119 comp_func_solid_SourceAtop_template<Argb32Operations>(dest, length, color, const_alpha);
1120}
1121
1122void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1123{
1124 comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
1125}
1126
1127#if QT_CONFIG(raster_64bit)
1128void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1129{
1130 comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
1131}
1132
1133void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1134{
1135 comp_func_SourceAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
1136}
1137#endif
1138
1139#if QT_CONFIG(raster_fp)
1140void QT_FASTCALL comp_func_solid_SourceAtop_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1141{
1142 comp_func_solid_SourceAtop_template<RgbaFPOperations>(dest, length, color, const_alpha);
1143}
1144
1145void QT_FASTCALL comp_func_SourceAtop_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1146{
1147 comp_func_SourceAtop_template<RgbaFPOperations>(dest, src, length, const_alpha);
1148}
1149#endif
1150
1151/*
1152 result = d*sa + s*dia
1153 dest = d*sa*ca + s*dia*ca + d *cia
1154 = s*ca * dia + d * (sa*ca + cia)
1155*/
1156template<class Ops>
1157inline static void comp_func_solid_DestinationAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1158{
1159 auto c = Ops::convert(color);
1160 auto sa = Ops::alpha(c);
1161 if (const_alpha != 255) {
1162 c = Ops::multiplyAlpha8bit(c, const_alpha);
1163 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
1164 sa = Ops::add(Ops::alpha(c), cia);
1165 }
1166
1167 for (int i = 0; i < length; ++i) {
1168 auto d = Ops::load(&dest[i]);
1169 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sa));
1170 }
1171}
1172
1173template<class Ops>
1174inline static void comp_func_DestinationAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1175 const typename Ops::Type *Q_DECL_RESTRICT src,
1176 int length, uint const_alpha)
1177{
1178 if (const_alpha == 255) {
1179 for (int i = 0; i < length; ++i) {
1180 auto s = Ops::load(&src[i]);
1181 auto d = Ops::load(&dest[i]);
1182 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::alpha(s)));
1183 }
1184 } else {
1185 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
1186 for (int i = 0; i < length; ++i) {
1187 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
1188 auto d = Ops::load(&dest[i]);
1189 auto sa = Ops::add(Ops::alpha(s), cia);
1190 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, sa));
1191 }
1192 }
1193}
1194
1195void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
1196{
1197 comp_func_solid_DestinationAtop_template<Argb32Operations>(dest, length, color, const_alpha);
1198}
1199
1200void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1201{
1202 comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
1203}
1204
1205#if QT_CONFIG(raster_64bit)
1206void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1207{
1208 comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
1209}
1210
1211void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1212{
1213 comp_func_DestinationAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
1214}
1215#endif
1216
1217#if QT_CONFIG(raster_fp)
1218void QT_FASTCALL comp_func_solid_DestinationAtop_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1219{
1220 comp_func_solid_DestinationAtop_template<RgbaFPOperations>(dest, length, color, const_alpha);
1221}
1222
1223void QT_FASTCALL comp_func_DestinationAtop_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1224{
1225 comp_func_DestinationAtop_template<RgbaFPOperations>(dest, src, length, const_alpha);
1226}
1227#endif
1228
1229/*
1230 result = d*sia + s*dia
1231 dest = d*sia*ca + s*dia*ca + d *cia
1232 = s*ca * dia + d * (sia*ca + cia)
1233 = s*ca * dia + d * (1 - sa*ca)
1234*/
1235template<class Ops>
1236inline static void comp_func_solid_XOR_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1237{
1238 auto c = Ops::convert(color);
1239 if (const_alpha != 255)
1240 c = Ops::multiplyAlpha8bit(c, const_alpha);
1241
1242 auto sia = Ops::invAlpha(c);
1243 for (int i = 0; i < length; ++i) {
1244 auto d = Ops::load(&dest[i]);
1245 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sia));
1246 }
1247}
1248
1249template<class Ops>
1250inline static void comp_func_XOR_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1251 const typename Ops::Type *Q_DECL_RESTRICT src,
1252 int length, uint const_alpha)
1253{
1254 if (const_alpha == 255) {
1255 for (int i = 0; i < length; ++i) {
1256 auto d = Ops::load(&dest[i]);
1257 auto s = Ops::load(&src[i]);
1258 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
1259 }
1260 } else {
1261 for (int i = 0; i < length; ++i) {
1262 auto d = Ops::load(&dest[i]);
1263 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
1264 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
1265 }
1266 }
1267}
1268
1269void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
1270{
1271 comp_func_solid_XOR_template<Argb32Operations>(dest, length, color, const_alpha);
1272}
1273
1274void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1275{
1276 comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
1277}
1278
1279#if QT_CONFIG(raster_64bit)
1280void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1281{
1282 comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
1283}
1284
1285void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1286{
1287 comp_func_XOR_template<Rgba64Operations>(dest, src, length, const_alpha);
1288}
1289#endif
1290
1291#if QT_CONFIG(raster_fp)
1292void QT_FASTCALL comp_func_solid_XOR_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1293{
1294 comp_func_solid_XOR_template<RgbaFPOperations>(dest, length, color, const_alpha);
1295}
1296
1297void QT_FASTCALL comp_func_XOR_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1298{
1299 comp_func_XOR_template<RgbaFPOperations>(dest, src, length, const_alpha);
1300}
1301#endif
1302
1303struct QFullCoverage {
1304 inline void store(uint *dest, const uint src) const
1305 {
1306 *dest = src;
1307 }
1308#if QT_CONFIG(raster_64bit)
1309 inline void store(QRgba64 *dest, const QRgba64 src) const
1310 {
1311 *dest = src;
1312 }
1313#endif
1314#if QT_CONFIG(raster_fp)
1315 inline void store(QRgbaFloat32 *dest, const QRgbaFloat32 src) const
1316 {
1317 *dest = src;
1318 }
1319#endif
1320};
1321
1322struct QPartialCoverage {
1323 inline QPartialCoverage(uint const_alpha)
1324 : ca(const_alpha)
1325 , ica(255 - const_alpha)
1326 {
1327 }
1328
1329 template<typename Op>
1330 inline void store_template(typename Op::Type *dest, const typename Op::Type src) const
1331 {
1332 Op::store(dest, Op::interpolate8bit(Op::convert(src), ca, Op::load(dest), ica));
1333 }
1334 inline void store(uint *dest, const uint src) const
1335 {
1336 store_template<Argb32Operations>(dest, src);
1337 }
1338#if QT_CONFIG(raster_64bit)
1339 inline void store(QRgba64 *dest, const QRgba64 src) const
1340 {
1341 store_template<Rgba64Operations>(dest, src);
1342 }
1343#endif
1344#if QT_CONFIG(raster_fp)
1345 inline void store(QRgbaFloat32 *dest, const QRgbaFloat32 src) const
1346 {
1347 store_template<RgbaFPOperations>(dest, src);
1348 }
1349#endif
1350
1351private:
1352 const uint ca;
1353 const uint ica;
1354};
1355
1356static inline int mix_alpha(int da, int sa)
1357{
1358 return 255 - qt_div_255(x: (255 - sa) * (255 - da));
1359}
1360
1361#if QT_CONFIG(raster_64bit)
1362static inline uint mix_alpha_rgb64(uint da, uint sa)
1363{
1364 return 65535U - qt_div_65535(x: (65535U - sa) * (65535U - da));
1365}
1366#endif
1367
1368#if QT_CONFIG(raster_fp)
1369static inline float mix_alpha_rgbafp(float da, float sa)
1370{
1371 return 1.0f - (1.0f - sa) * (1.0f - da);
1372}
1373#endif
1374
1375/*
1376 Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
1377 = Sca + Dca
1378*/
1379template<class Ops>
1380inline static void comp_func_solid_Plus_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1381{
1382 auto c = Ops::convert(color);
1383 if (const_alpha == 255) {
1384 for (int i = 0; i < length; ++i) {
1385 auto d = Ops::load(&dest[i]);
1386 d = Ops::plus(d, c);
1387 Ops::store(&dest[i], d);
1388 }
1389 } else {
1390 uint ia = 255 - const_alpha;
1391 for (int i = 0; i < length; ++i) {
1392 auto d = Ops::load(&dest[i]);
1393 d = Ops::interpolate8bit(Ops::plus(d, c), const_alpha, d, ia);
1394 Ops::store(&dest[i], d);
1395 }
1396 }
1397}
1398
1399template<class Ops>
1400inline static void comp_func_Plus_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1401 const typename Ops::Type *Q_DECL_RESTRICT src,
1402 int length, uint const_alpha)
1403{
1404 if (const_alpha == 255) {
1405 for (int i = 0; i < length; ++i) {
1406 auto d = Ops::load(&dest[i]);
1407 auto s = Ops::load(&src[i]);
1408 d = Ops::plus(d, s);
1409 Ops::store(&dest[i], d);
1410 }
1411 } else {
1412 uint ia = 255 - const_alpha;
1413 for (int i = 0; i < length; ++i) {
1414 auto d = Ops::load(&dest[i]);
1415 auto s = Ops::load(&src[i]);
1416 d = Ops::interpolate8bit(Ops::plus(d, s), const_alpha, d, ia);
1417 Ops::store(&dest[i], d);
1418 }
1419 }
1420}
1421
1422void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
1423{
1424 comp_func_solid_Plus_template<Argb32Operations>(dest, length, color, const_alpha);
1425}
1426
1427void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1428{
1429 comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
1430}
1431
1432#if QT_CONFIG(raster_64bit)
1433void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1434{
1435 comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
1436}
1437
1438void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1439{
1440 comp_func_Plus_template<Rgba64Operations>(dest, src, length, const_alpha);
1441}
1442#endif
1443
1444#if QT_CONFIG(raster_fp)
1445void QT_FASTCALL comp_func_solid_Plus_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1446{
1447 comp_func_solid_Plus_template<RgbaFPOperations>(dest, length, color, const_alpha);
1448}
1449
1450void QT_FASTCALL comp_func_Plus_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1451{
1452 comp_func_Plus_template<RgbaFPOperations>(dest, src, length, const_alpha);
1453}
1454#endif
1455
1456/*
1457 Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
1458*/
1459static inline int multiply_op(int dst, int src, int da, int sa)
1460{
1461 return qt_div_255(x: src * dst + src * (255 - da) + dst * (255 - sa));
1462}
1463
1464template <typename T>
1465static inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
1466{
1467 int sa = qAlpha(rgb: color);
1468 int sr = qRed(rgb: color);
1469 int sg = qGreen(rgb: color);
1470 int sb = qBlue(rgb: color);
1471
1472 for (int i = 0; i < length; ++i) {
1473 uint d = dest[i];
1474 int da = qAlpha(rgb: d);
1475
1476#define OP(a, b) multiply_op(a, b, da, sa)
1477 int r = OP( qRed(d), sr);
1478 int b = OP( qBlue(d), sb);
1479 int g = OP(qGreen(d), sg);
1480 int a = mix_alpha(da, sa);
1481#undef OP
1482
1483 coverage.store(&dest[i], qRgba(r, g, b, a));
1484 }
1485}
1486
1487void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
1488{
1489 if (const_alpha == 255)
1490 comp_func_solid_Multiply_impl(dest, length, color, coverage: QFullCoverage());
1491 else
1492 comp_func_solid_Multiply_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1493}
1494
1495#if QT_CONFIG(raster_64bit)
1496static inline uint multiply_op_rgb64(uint dst, uint src, uint da, uint sa)
1497{
1498 return qt_div_65535(x: src * dst + src * (65535U - da) + dst * (65535U - sa));
1499}
1500
1501template <typename T>
1502static inline void comp_func_solid_Multiply_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1503{
1504 uint sa = color.alpha();
1505 uint sr = color.red();
1506 uint sg = color.green();
1507 uint sb = color.blue();
1508
1509 for (int i = 0; i < length; ++i) {
1510 QRgba64 d = dest[i];
1511 uint da = d.alpha();
1512
1513#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
1514 uint r = OP( d.red(), sr);
1515 uint b = OP( d.blue(), sb);
1516 uint g = OP(d.green(), sg);
1517 uint a = mix_alpha_rgb64(da, sa);
1518#undef OP
1519
1520 coverage.store(&dest[i], qRgba64(r, g, b, a));
1521 }
1522}
1523
1524void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1525{
1526 if (const_alpha == 255)
1527 comp_func_solid_Multiply_impl(dest, length, color, coverage: QFullCoverage());
1528 else
1529 comp_func_solid_Multiply_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1530}
1531#endif
1532
1533#if QT_CONFIG(raster_fp)
1534static inline float multiply_op_rgbafp(float dst, float src, float da, float sa)
1535{
1536 return src * dst + src * (1.0f - da) + dst * (1.0f - sa);
1537}
1538
1539template <typename T>
1540static inline void comp_func_solid_Multiply_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
1541{
1542 float sa = color.alpha();
1543 float sr = color.red();
1544 float sg = color.green();
1545 float sb = color.blue();
1546
1547 for (int i = 0; i < length; ++i) {
1548 QRgbaFloat32 d = dest[i];
1549 float da = d.alpha();
1550
1551#define OP(a, b) multiply_op_rgbafp(a, b, da, sa)
1552 float r = OP( d.red(), sr);
1553 float b = OP( d.blue(), sb);
1554 float g = OP(d.green(), sg);
1555 float a = mix_alpha_rgbafp(da, sa);
1556#undef OP
1557
1558 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
1559 }
1560}
1561
1562void QT_FASTCALL comp_func_solid_Multiply_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1563{
1564 if (const_alpha == 255)
1565 comp_func_solid_Multiply_impl(dest, length, color, coverage: QFullCoverage());
1566 else
1567 comp_func_solid_Multiply_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1568}
1569#endif
1570
1571
1572template <typename T>
1573static inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1574{
1575 for (int i = 0; i < length; ++i) {
1576 uint d = dest[i];
1577 uint s = src[i];
1578
1579 int da = qAlpha(rgb: d);
1580 int sa = qAlpha(rgb: s);
1581
1582#define OP(a, b) multiply_op(a, b, da, sa)
1583 int r = OP( qRed(d), qRed(s));
1584 int b = OP( qBlue(d), qBlue(s));
1585 int g = OP(qGreen(d), qGreen(s));
1586 int a = mix_alpha(da, sa);
1587#undef OP
1588
1589 coverage.store(&dest[i], qRgba(r, g, b, a));
1590 }
1591}
1592
1593void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1594{
1595 if (const_alpha == 255)
1596 comp_func_Multiply_impl(dest, src, length, coverage: QFullCoverage());
1597 else
1598 comp_func_Multiply_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1599}
1600
1601#if QT_CONFIG(raster_64bit)
1602template <typename T>
1603static inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1604{
1605 for (int i = 0; i < length; ++i) {
1606 QRgba64 d = dest[i];
1607 QRgba64 s = src[i];
1608
1609 uint da = d.alpha();
1610 uint sa = s.alpha();
1611
1612#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
1613 uint r = OP( d.red(), s.red());
1614 uint b = OP( d.blue(), s.blue());
1615 uint g = OP(d.green(), s.green());
1616 uint a = mix_alpha_rgb64(da, sa);
1617#undef OP
1618
1619 coverage.store(&dest[i], qRgba64(r, g, b, a));
1620 }
1621}
1622
1623void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1624{
1625 if (const_alpha == 255)
1626 comp_func_Multiply_impl(dest, src, length, coverage: QFullCoverage());
1627 else
1628 comp_func_Multiply_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1629}
1630#endif
1631
1632#if QT_CONFIG(raster_fp)
1633template <typename T>
1634static inline void comp_func_Multiply_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
1635{
1636 for (int i = 0; i < length; ++i) {
1637 QRgbaFloat32 d = dest[i];
1638 QRgbaFloat32 s = src[i];
1639
1640 float da = d.alpha();
1641 float sa = s.alpha();
1642
1643#define OP(a, b) multiply_op_rgbafp(a, b, da, sa)
1644 float r = OP( d.red(), s.red());
1645 float b = OP( d.blue(), s.blue());
1646 float g = OP(d.green(), s.green());
1647 float a = mix_alpha_rgbafp(da, sa);
1648#undef OP
1649
1650 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
1651 }
1652}
1653
1654void QT_FASTCALL comp_func_Multiply_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1655{
1656 if (const_alpha == 255)
1657 comp_func_Multiply_impl(dest, src, length, coverage: QFullCoverage());
1658 else
1659 comp_func_Multiply_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1660}
1661#endif
1662
1663/*
1664 Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
1665 = Sca + Dca - Sca.Dca
1666*/
1667template <typename T>
1668static inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
1669{
1670 int sa = qAlpha(rgb: color);
1671 int sr = qRed(rgb: color);
1672 int sg = qGreen(rgb: color);
1673 int sb = qBlue(rgb: color);
1674
1675 for (int i = 0; i < length; ++i) {
1676 uint d = dest[i];
1677 int da = qAlpha(rgb: d);
1678
1679#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
1680 int r = OP( qRed(d), sr);
1681 int b = OP( qBlue(d), sb);
1682 int g = OP(qGreen(d), sg);
1683 int a = mix_alpha(da, sa);
1684#undef OP
1685
1686 coverage.store(&dest[i], qRgba(r, g, b, a));
1687 }
1688}
1689
1690void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
1691{
1692 if (const_alpha == 255)
1693 comp_func_solid_Screen_impl(dest, length, color, coverage: QFullCoverage());
1694 else
1695 comp_func_solid_Screen_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1696}
1697
1698#if QT_CONFIG(raster_64bit)
1699template <typename T>
1700static inline void comp_func_solid_Screen_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1701{
1702 uint sa = color.alpha();
1703 uint sr = color.red();
1704 uint sg = color.green();
1705 uint sb = color.blue();
1706
1707 for (int i = 0; i < length; ++i) {
1708 QRgba64 d = dest[i];
1709 uint da = d.alpha();
1710
1711#define OP(a, b) 65535 - qt_div_65535((65535U-a) * (65535U-b))
1712 uint r = OP( d.red(), sr);
1713 uint b = OP( d.blue(), sb);
1714 uint g = OP(d.green(), sg);
1715 uint a = mix_alpha_rgb64(da, sa);
1716#undef OP
1717
1718 coverage.store(&dest[i], qRgba64(r, g, b, a));
1719 }
1720}
1721
1722void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1723{
1724 if (const_alpha == 255)
1725 comp_func_solid_Screen_impl(dest, length, color, coverage: QFullCoverage());
1726 else
1727 comp_func_solid_Screen_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1728}
1729#endif
1730
1731#if QT_CONFIG(raster_fp)
1732template <typename T>
1733static inline void comp_func_solid_Screen_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
1734{
1735 float sa = color.alpha();
1736 float sr = color.red();
1737 float sg = color.green();
1738 float sb = color.blue();
1739
1740 for (int i = 0; i < length; ++i) {
1741 QRgbaFloat32 d = dest[i];
1742 float da = d.alpha();
1743
1744#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b)))
1745 float r = OP( d.red(), sr);
1746 float b = OP( d.blue(), sb);
1747 float g = OP(d.green(), sg);
1748 float a = mix_alpha_rgbafp(da, sa);
1749#undef OP
1750
1751 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
1752 }
1753}
1754
1755void QT_FASTCALL comp_func_solid_Screen_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1756{
1757 if (const_alpha == 255)
1758 comp_func_solid_Screen_impl(dest, length, color, coverage: QFullCoverage());
1759 else
1760 comp_func_solid_Screen_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1761}
1762#endif
1763
1764template <typename T>
1765static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1766{
1767 for (int i = 0; i < length; ++i) {
1768 uint d = dest[i];
1769 uint s = src[i];
1770
1771 int da = qAlpha(rgb: d);
1772 int sa = qAlpha(rgb: s);
1773
1774#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
1775 int r = OP( qRed(d), qRed(s));
1776 int b = OP( qBlue(d), qBlue(s));
1777 int g = OP(qGreen(d), qGreen(s));
1778 int a = mix_alpha(da, sa);
1779#undef OP
1780
1781 coverage.store(&dest[i], qRgba(r, g, b, a));
1782 }
1783}
1784
1785void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
1786{
1787 if (const_alpha == 255)
1788 comp_func_Screen_impl(dest, src, length, coverage: QFullCoverage());
1789 else
1790 comp_func_Screen_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1791}
1792
1793#if QT_CONFIG(raster_64bit)
1794template <typename T>
1795static inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1796{
1797 for (int i = 0; i < length; ++i) {
1798 QRgba64 d = dest[i];
1799 QRgba64 s = src[i];
1800
1801 uint da = d.alpha();
1802 uint sa = s.alpha();
1803
1804#define OP(a, b) 65535U - qt_div_65535((65535U-a) * (65535U-b))
1805 uint r = OP( d.red(), s.red());
1806 uint b = OP( d.blue(), s.blue());
1807 uint g = OP(d.green(), s.green());
1808 uint a = mix_alpha_rgb64(da, sa);
1809#undef OP
1810
1811 coverage.store(&dest[i], qRgba64(r, g, b, a));
1812 }
1813}
1814
1815void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int length, uint const_alpha)
1816{
1817 if (const_alpha == 255)
1818 comp_func_Screen_impl(dest, src, length, coverage: QFullCoverage());
1819 else
1820 comp_func_Screen_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1821}
1822#endif
1823
1824#if QT_CONFIG(raster_fp)
1825template <typename T>
1826static inline void comp_func_Screen_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
1827{
1828 for (int i = 0; i < length; ++i) {
1829 QRgbaFloat32 d = dest[i];
1830 QRgbaFloat32 s = src[i];
1831
1832 float da = d.alpha();
1833 float sa = s.alpha();
1834
1835#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b)))
1836 float r = OP( d.red(), s.red());
1837 float b = OP( d.blue(), s.blue());
1838 float g = OP(d.green(), s.green());
1839 float a = mix_alpha_rgbafp(da, sa);
1840#undef OP
1841
1842 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
1843 }
1844}
1845
1846void QT_FASTCALL comp_func_Screen_rgbafp(QRgbaFloat32 *dest, const QRgbaFloat32 *src, int length, uint const_alpha)
1847{
1848 if (const_alpha == 255)
1849 comp_func_Screen_impl(dest, src, length, coverage: QFullCoverage());
1850 else
1851 comp_func_Screen_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1852}
1853#endif
1854
1855/*
1856 if 2.Dca < Da
1857 Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
1858 otherwise
1859 Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
1860*/
1861static inline int overlay_op(int dst, int src, int da, int sa)
1862{
1863 const int temp = src * (255 - da) + dst * (255 - sa);
1864 if (2 * dst < da)
1865 return qt_div_255(x: 2 * src * dst + temp);
1866 else
1867 return qt_div_255(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
1868}
1869
1870template <typename T>
1871static inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
1872{
1873 int sa = qAlpha(rgb: color);
1874 int sr = qRed(rgb: color);
1875 int sg = qGreen(rgb: color);
1876 int sb = qBlue(rgb: color);
1877
1878 for (int i = 0; i < length; ++i) {
1879 uint d = dest[i];
1880 int da = qAlpha(rgb: d);
1881
1882#define OP(a, b) overlay_op(a, b, da, sa)
1883 int r = OP( qRed(d), sr);
1884 int b = OP( qBlue(d), sb);
1885 int g = OP(qGreen(d), sg);
1886 int a = mix_alpha(da, sa);
1887#undef OP
1888
1889 coverage.store(&dest[i], qRgba(r, g, b, a));
1890 }
1891}
1892
1893void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
1894{
1895 if (const_alpha == 255)
1896 comp_func_solid_Overlay_impl(dest, length, color, coverage: QFullCoverage());
1897 else
1898 comp_func_solid_Overlay_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1899}
1900
1901#if QT_CONFIG(raster_64bit)
1902static inline uint overlay_op_rgb64(uint dst, uint src, uint da, uint sa)
1903{
1904 const uint temp = src * (65535U - da) + dst * (65535U - sa);
1905 if (2 * dst < da)
1906 return qt_div_65535(x: 2 * src * dst + temp);
1907 else
1908 return qt_div_65535(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
1909}
1910
1911template <typename T>
1912static inline void comp_func_solid_Overlay_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1913{
1914 uint sa = color.alpha();
1915 uint sr = color.red();
1916 uint sg = color.green();
1917 uint sb = color.blue();
1918
1919 for (int i = 0; i < length; ++i) {
1920 QRgba64 d = dest[i];
1921 uint da = d.alpha();
1922
1923#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
1924 uint r = OP( d.red(), sr);
1925 uint b = OP( d.blue(), sb);
1926 uint g = OP(d.green(), sg);
1927 uint a = mix_alpha_rgb64(da, sa);
1928#undef OP
1929
1930 coverage.store(&dest[i], qRgba64(r, g, b, a));
1931 }
1932}
1933
1934void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1935{
1936 if (const_alpha == 255)
1937 comp_func_solid_Overlay_impl(dest, length, color, coverage: QFullCoverage());
1938 else
1939 comp_func_solid_Overlay_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1940}
1941#endif
1942
1943#if QT_CONFIG(raster_fp)
1944static inline float overlay_op_rgbafp(float dst, float src, float da, float sa)
1945{
1946 const float temp = src * (1.0f - da) + dst * (1.0f - sa);
1947 if (2 * dst < da)
1948 return 2 * src * dst + temp;
1949 else
1950 return sa * da - 2 * (da - dst) * (sa - src) + temp;
1951}
1952
1953template <typename T>
1954static inline void comp_func_solid_Overlay_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
1955{
1956 float sa = color.alpha();
1957 float sr = color.red();
1958 float sg = color.green();
1959 float sb = color.blue();
1960
1961 for (int i = 0; i < length; ++i) {
1962 QRgbaFloat32 d = dest[i];
1963 float da = d.alpha();
1964
1965#define OP(a, b) overlay_op_rgbafp(a, b, da, sa)
1966 float r = OP( d.red(), sr);
1967 float b = OP( d.blue(), sb);
1968 float g = OP(d.green(), sg);
1969 float a = mix_alpha_rgbafp(da, sa);
1970#undef OP
1971
1972 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
1973 }
1974}
1975
1976void QT_FASTCALL comp_func_solid_Overlay_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
1977{
1978 if (const_alpha == 255)
1979 comp_func_solid_Overlay_impl(dest, length, color, coverage: QFullCoverage());
1980 else
1981 comp_func_solid_Overlay_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1982}
1983#endif
1984
1985template <typename T>
1986static inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1987{
1988 for (int i = 0; i < length; ++i) {
1989 uint d = dest[i];
1990 uint s = src[i];
1991
1992 int da = qAlpha(rgb: d);
1993 int sa = qAlpha(rgb: s);
1994
1995#define OP(a, b) overlay_op(a, b, da, sa)
1996 int r = OP( qRed(d), qRed(s));
1997 int b = OP( qBlue(d), qBlue(s));
1998 int g = OP(qGreen(d), qGreen(s));
1999 int a = mix_alpha(da, sa);
2000#undef OP
2001
2002 coverage.store(&dest[i], qRgba(r, g, b, a));
2003 }
2004}
2005
2006void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2007{
2008 if (const_alpha == 255)
2009 comp_func_Overlay_impl(dest, src, length, coverage: QFullCoverage());
2010 else
2011 comp_func_Overlay_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2012}
2013
2014#if QT_CONFIG(raster_64bit)
2015template <typename T>
2016static inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2017{
2018 for (int i = 0; i < length; ++i) {
2019 QRgba64 d = dest[i];
2020 QRgba64 s = src[i];
2021
2022 uint da = d.alpha();
2023 uint sa = s.alpha();
2024
2025#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
2026 uint r = OP( d.red(), s.red());
2027 uint b = OP( d.blue(), s.blue());
2028 uint g = OP(d.green(), s.green());
2029 uint a = mix_alpha_rgb64(da, sa);
2030#undef OP
2031
2032 coverage.store(&dest[i], qRgba64(r, g, b, a));
2033 }
2034}
2035
2036void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2037{
2038 if (const_alpha == 255)
2039 comp_func_Overlay_impl(dest, src, length, coverage: QFullCoverage());
2040 else
2041 comp_func_Overlay_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2042}
2043#endif
2044
2045#if QT_CONFIG(raster_fp)
2046template <typename T>
2047static inline void comp_func_Overlay_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
2048{
2049 for (int i = 0; i < length; ++i) {
2050 QRgbaFloat32 d = dest[i];
2051 QRgbaFloat32 s = src[i];
2052
2053 float da = d.alpha();
2054 float sa = s.alpha();
2055
2056#define OP(a, b) overlay_op_rgbafp(a, b, da, sa)
2057 float r = OP( d.red(), s.red());
2058 float b = OP( d.blue(), s.blue());
2059 float g = OP(d.green(), s.green());
2060 float a = mix_alpha_rgbafp(da, sa);
2061#undef OP
2062
2063 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2064 }
2065}
2066
2067void QT_FASTCALL comp_func_Overlay_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2068{
2069 if (const_alpha == 255)
2070 comp_func_Overlay_impl(dest, src, length, coverage: QFullCoverage());
2071 else
2072 comp_func_Overlay_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2073}
2074#endif
2075
2076/*
2077 Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
2078 Da' = Sa + Da - Sa.Da
2079*/
2080static inline int darken_op(int dst, int src, int da, int sa)
2081{
2082 return qt_div_255(x: qMin(a: src * da, b: dst * sa) + src * (255 - da) + dst * (255 - sa));
2083}
2084
2085template <typename T>
2086static inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
2087{
2088 int sa = qAlpha(rgb: color);
2089 int sr = qRed(rgb: color);
2090 int sg = qGreen(rgb: color);
2091 int sb = qBlue(rgb: color);
2092
2093 for (int i = 0; i < length; ++i) {
2094 uint d = dest[i];
2095 int da = qAlpha(rgb: d);
2096
2097#define OP(a, b) darken_op(a, b, da, sa)
2098 int r = OP( qRed(d), sr);
2099 int b = OP( qBlue(d), sb);
2100 int g = OP(qGreen(d), sg);
2101 int a = mix_alpha(da, sa);
2102#undef OP
2103
2104 coverage.store(&dest[i], qRgba(r, g, b, a));
2105 }
2106}
2107
2108void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
2109{
2110 if (const_alpha == 255)
2111 comp_func_solid_Darken_impl(dest, length, color, coverage: QFullCoverage());
2112 else
2113 comp_func_solid_Darken_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2114}
2115
2116#if QT_CONFIG(raster_64bit)
2117static inline uint darken_op_rgb64(uint dst, uint src, uint da, uint sa)
2118{
2119 return qt_div_65535(x: qMin(a: src * da, b: dst * sa) + src * (65535U - da) + dst * (65535U - sa));
2120}
2121
2122template <typename T>
2123static inline void comp_func_solid_Darken_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2124{
2125 uint sa = color.alpha();
2126 uint sr = color.red();
2127 uint sg = color.green();
2128 uint sb = color.blue();
2129
2130 for (int i = 0; i < length; ++i) {
2131 QRgba64 d = dest[i];
2132 uint da = d.alpha();
2133
2134#define OP(a, b) darken_op_rgb64(a, b, da, sa)
2135 uint r = OP( d.red(), sr);
2136 uint b = OP( d.blue(), sb);
2137 uint g = OP(d.green(), sg);
2138 uint a = mix_alpha_rgb64(da, sa);
2139#undef OP
2140
2141 coverage.store(&dest[i], qRgba64(r, g, b, a));
2142 }
2143}
2144
2145void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2146{
2147 if (const_alpha == 255)
2148 comp_func_solid_Darken_impl(dest, length, color, coverage: QFullCoverage());
2149 else
2150 comp_func_solid_Darken_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2151}
2152#endif
2153
2154#if QT_CONFIG(raster_fp)
2155static inline float darken_op_rgbafp(float dst, float src, float da, float sa)
2156{
2157 return qMin(a: src * da, b: dst * sa) + src * (1.0f - da) + dst * (1.0f - sa);
2158}
2159
2160template <typename T>
2161static inline void comp_func_solid_Darken_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
2162{
2163 float sa = color.alpha();
2164 float sr = color.red();
2165 float sg = color.green();
2166 float sb = color.blue();
2167
2168 for (int i = 0; i < length; ++i) {
2169 QRgbaFloat32 d = dest[i];
2170 float da = d.alpha();
2171
2172#define OP(a, b) darken_op_rgbafp(a, b, da, sa)
2173 float r = OP( d.red(), sr);
2174 float b = OP( d.blue(), sb);
2175 float g = OP(d.green(), sg);
2176 float a = mix_alpha_rgbafp(da, sa);
2177#undef OP
2178
2179 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2180 }
2181}
2182
2183void QT_FASTCALL comp_func_solid_Darken_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
2184{
2185 if (const_alpha == 255)
2186 comp_func_solid_Darken_impl(dest, length, color, coverage: QFullCoverage());
2187 else
2188 comp_func_solid_Darken_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2189}
2190#endif
2191
2192template <typename T>
2193static inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2194{
2195 for (int i = 0; i < length; ++i) {
2196 uint d = dest[i];
2197 uint s = src[i];
2198
2199 int da = qAlpha(rgb: d);
2200 int sa = qAlpha(rgb: s);
2201
2202#define OP(a, b) darken_op(a, b, da, sa)
2203 int r = OP( qRed(d), qRed(s));
2204 int b = OP( qBlue(d), qBlue(s));
2205 int g = OP(qGreen(d), qGreen(s));
2206 int a = mix_alpha(da, sa);
2207#undef OP
2208
2209 coverage.store(&dest[i], qRgba(r, g, b, a));
2210 }
2211}
2212
2213void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2214{
2215 if (const_alpha == 255)
2216 comp_func_Darken_impl(dest, src, length, coverage: QFullCoverage());
2217 else
2218 comp_func_Darken_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2219}
2220
2221#if QT_CONFIG(raster_64bit)
2222template <typename T>
2223static inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2224{
2225 for (int i = 0; i < length; ++i) {
2226 QRgba64 d = dest[i];
2227 QRgba64 s = src[i];
2228
2229 uint da = d.alpha();
2230 uint sa = s.alpha();
2231
2232#define OP(a, b) darken_op_rgb64(a, b, da, sa)
2233 uint r = OP( d.red(), s.red());
2234 uint b = OP( d.blue(), s.blue());
2235 uint g = OP(d.green(), s.green());
2236 uint a = mix_alpha_rgb64(da, sa);
2237#undef OP
2238
2239 coverage.store(&dest[i], qRgba64(r, g, b, a));
2240 }
2241}
2242
2243void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2244{
2245 if (const_alpha == 255)
2246 comp_func_Darken_impl(dest, src, length, coverage: QFullCoverage());
2247 else
2248 comp_func_Darken_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2249}
2250#endif
2251
2252#if QT_CONFIG(raster_fp)
2253template <typename T>
2254static inline void comp_func_Darken_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
2255{
2256 for (int i = 0; i < length; ++i) {
2257 QRgbaFloat32 d = dest[i];
2258 QRgbaFloat32 s = src[i];
2259
2260 float da = d.alpha();
2261 float sa = s.alpha();
2262
2263#define OP(a, b) darken_op_rgbafp(a, b, da, sa)
2264 float r = OP( d.red(), s.red());
2265 float b = OP( d.blue(), s.blue());
2266 float g = OP(d.green(), s.green());
2267 float a = mix_alpha_rgbafp(da, sa);
2268#undef OP
2269
2270 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2271 }
2272}
2273
2274void QT_FASTCALL comp_func_Darken_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2275{
2276 if (const_alpha == 255)
2277 comp_func_Darken_impl(dest, src, length, coverage: QFullCoverage());
2278 else
2279 comp_func_Darken_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2280}
2281#endif
2282
2283/*
2284 Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
2285 Da' = Sa + Da - Sa.Da
2286*/
2287static inline int lighten_op(int dst, int src, int da, int sa)
2288{
2289 return qt_div_255(x: qMax(a: src * da, b: dst * sa) + src * (255 - da) + dst * (255 - sa));
2290}
2291
2292template <typename T>
2293static inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
2294{
2295 int sa = qAlpha(rgb: color);
2296 int sr = qRed(rgb: color);
2297 int sg = qGreen(rgb: color);
2298 int sb = qBlue(rgb: color);
2299
2300 for (int i = 0; i < length; ++i) {
2301 uint d = dest[i];
2302 int da = qAlpha(rgb: d);
2303
2304#define OP(a, b) lighten_op(a, b, da, sa)
2305 int r = OP( qRed(d), sr);
2306 int b = OP( qBlue(d), sb);
2307 int g = OP(qGreen(d), sg);
2308 int a = mix_alpha(da, sa);
2309#undef OP
2310
2311 coverage.store(&dest[i], qRgba(r, g, b, a));
2312 }
2313}
2314
2315void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
2316{
2317 if (const_alpha == 255)
2318 comp_func_solid_Lighten_impl(dest, length, color, coverage: QFullCoverage());
2319 else
2320 comp_func_solid_Lighten_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2321}
2322
2323
2324#if QT_CONFIG(raster_64bit)
2325static inline uint lighten_op_rgb64(uint dst, uint src, uint da, uint sa)
2326{
2327 return qt_div_65535(x: qMax(a: src * da, b: dst * sa) + src * (65535U - da) + dst * (65535U - sa));
2328}
2329
2330template <typename T>
2331static inline void comp_func_solid_Lighten_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2332{
2333 uint sa = color.alpha();
2334 uint sr = color.red();
2335 uint sg = color.green();
2336 uint sb = color.blue();
2337
2338 for (int i = 0; i < length; ++i) {
2339 QRgba64 d = dest[i];
2340 uint da = d.alpha();
2341
2342#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
2343 uint r = OP( d.red(), sr);
2344 uint b = OP( d.blue(), sb);
2345 uint g = OP(d.green(), sg);
2346 uint a = mix_alpha_rgb64(da, sa);
2347#undef OP
2348
2349 coverage.store(&dest[i], qRgba64(r, g, b, a));
2350 }
2351}
2352
2353void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2354{
2355 if (const_alpha == 255)
2356 comp_func_solid_Lighten_impl(dest, length, color, coverage: QFullCoverage());
2357 else
2358 comp_func_solid_Lighten_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2359}
2360#endif
2361
2362#if QT_CONFIG(raster_fp)
2363static inline float lighten_op_rgbafp(float dst, float src, float da, float sa)
2364{
2365 return qMax(a: src * da, b: dst * sa) + src * (1.0f - da) + dst * (1.0f - sa);
2366}
2367
2368template <typename T>
2369static inline void comp_func_solid_Lighten_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
2370{
2371 float sa = color.alpha();
2372 float sr = color.red();
2373 float sg = color.green();
2374 float sb = color.blue();
2375
2376 for (int i = 0; i < length; ++i) {
2377 QRgbaFloat32 d = dest[i];
2378 float da = d.alpha();
2379
2380#define OP(a, b) lighten_op_rgbafp(a, b, da, sa)
2381 float r = OP( d.red(), sr);
2382 float b = OP( d.blue(), sb);
2383 float g = OP(d.green(), sg);
2384 float a = mix_alpha_rgbafp(da, sa);
2385#undef OP
2386
2387 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2388 }
2389}
2390
2391void QT_FASTCALL comp_func_solid_Lighten_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
2392{
2393 if (const_alpha == 255)
2394 comp_func_solid_Lighten_impl(dest, length, color, coverage: QFullCoverage());
2395 else
2396 comp_func_solid_Lighten_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2397}
2398#endif
2399
2400template <typename T>
2401static inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2402{
2403 for (int i = 0; i < length; ++i) {
2404 uint d = dest[i];
2405 uint s = src[i];
2406
2407 int da = qAlpha(rgb: d);
2408 int sa = qAlpha(rgb: s);
2409
2410#define OP(a, b) lighten_op(a, b, da, sa)
2411 int r = OP( qRed(d), qRed(s));
2412 int b = OP( qBlue(d), qBlue(s));
2413 int g = OP(qGreen(d), qGreen(s));
2414 int a = mix_alpha(da, sa);
2415#undef OP
2416
2417 coverage.store(&dest[i], qRgba(r, g, b, a));
2418 }
2419}
2420
2421void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2422{
2423 if (const_alpha == 255)
2424 comp_func_Lighten_impl(dest, src, length, coverage: QFullCoverage());
2425 else
2426 comp_func_Lighten_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2427}
2428
2429#if QT_CONFIG(raster_64bit)
2430template <typename T>
2431static inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2432{
2433 for (int i = 0; i < length; ++i) {
2434 QRgba64 d = dest[i];
2435 QRgba64 s = src[i];
2436
2437 uint da = d.alpha();
2438 uint sa = s.alpha();
2439
2440#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
2441 uint r = OP( d.red(), s.red());
2442 uint b = OP( d.blue(), s.blue());
2443 uint g = OP(d.green(), s.green());
2444 uint a = mix_alpha_rgb64(da, sa);
2445#undef OP
2446
2447 coverage.store(&dest[i], qRgba64(r, g, b, a));
2448 }
2449}
2450
2451void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2452{
2453 if (const_alpha == 255)
2454 comp_func_Lighten_impl(dest, src, length, coverage: QFullCoverage());
2455 else
2456 comp_func_Lighten_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2457}
2458#endif
2459
2460#if QT_CONFIG(raster_fp)
2461template <typename T>
2462static inline void comp_func_Lighten_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
2463{
2464 for (int i = 0; i < length; ++i) {
2465 QRgbaFloat32 d = dest[i];
2466 QRgbaFloat32 s = src[i];
2467
2468 float da = d.alpha();
2469 float sa = s.alpha();
2470
2471#define OP(a, b) lighten_op_rgbafp(a, b, da, sa)
2472 float r = OP( d.red(), s.red());
2473 float b = OP( d.blue(), s.blue());
2474 float g = OP(d.green(), s.green());
2475 float a = mix_alpha_rgbafp(da, sa);
2476#undef OP
2477
2478 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2479 }
2480}
2481
2482void QT_FASTCALL comp_func_Lighten_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2483{
2484 if (const_alpha == 255)
2485 comp_func_Lighten_impl(dest, src, length, coverage: QFullCoverage());
2486 else
2487 comp_func_Lighten_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2488}
2489#endif
2490
2491/*
2492 if Sca.Da + Dca.Sa > Sa.Da
2493 Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
2494 else if Sca == Sa
2495 Dca' = Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
2496 otherwise
2497 Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
2498*/
2499static inline int color_dodge_op(int dst, int src, int da, int sa)
2500{
2501 const int sa_da = sa * da;
2502 const int dst_sa = dst * sa;
2503 const int src_da = src * da;
2504
2505 const int temp = src * (255 - da) + dst * (255 - sa);
2506 if (src_da + dst_sa > sa_da)
2507 return qt_div_255(x: sa_da + temp);
2508 else if (src == sa || sa == 0)
2509 return qt_div_255(x: temp);
2510 else
2511 return qt_div_255(x: 255 * dst_sa / (255 - 255 * src / sa) + temp);
2512}
2513
2514template <typename T>
2515static inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
2516{
2517 int sa = qAlpha(rgb: color);
2518 int sr = qRed(rgb: color);
2519 int sg = qGreen(rgb: color);
2520 int sb = qBlue(rgb: color);
2521
2522 for (int i = 0; i < length; ++i) {
2523 uint d = dest[i];
2524 int da = qAlpha(rgb: d);
2525
2526#define OP(a,b) color_dodge_op(a, b, da, sa)
2527 int r = OP( qRed(d), sr);
2528 int b = OP( qBlue(d), sb);
2529 int g = OP(qGreen(d), sg);
2530 int a = mix_alpha(da, sa);
2531#undef OP
2532
2533 coverage.store(&dest[i], qRgba(r, g, b, a));
2534 }
2535}
2536
2537void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
2538{
2539 if (const_alpha == 255)
2540 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QFullCoverage());
2541 else
2542 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2543}
2544
2545#if QT_CONFIG(raster_64bit)
2546static inline uint color_dodge_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
2547{
2548 const qint64 sa_da = sa * da;
2549 const qint64 dst_sa = dst * sa;
2550 const qint64 src_da = src * da;
2551
2552 const qint64 temp = src * (65535U - da) + dst * (65535U - sa);
2553 if (src_da + dst_sa > sa_da)
2554 return qt_div_65535(x: sa_da + temp);
2555 else if (src == sa || sa == 0)
2556 return qt_div_65535(x: temp);
2557 else
2558 return qt_div_65535(x: 65535U * dst_sa / (65535U - 65535U * src / sa) + temp);
2559}
2560
2561template <typename T>
2562static inline void comp_func_solid_ColorDodge_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2563{
2564 uint sa = color.alpha();
2565 uint sr = color.red();
2566 uint sg = color.green();
2567 uint sb = color.blue();
2568
2569 for (int i = 0; i < length; ++i) {
2570 QRgba64 d = dest[i];
2571 uint da = d.alpha();
2572
2573#define OP(a,b) color_dodge_op_rgb64(a, b, da, sa)
2574 uint r = OP( d.red(), sr);
2575 uint b = OP( d.blue(), sb);
2576 uint g = OP(d.green(), sg);
2577 uint a = mix_alpha_rgb64(da, sa);
2578#undef OP
2579
2580 coverage.store(&dest[i], qRgba64(r, g, b, a));
2581 }
2582}
2583
2584void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2585{
2586 if (const_alpha == 255)
2587 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QFullCoverage());
2588 else
2589 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2590}
2591#endif
2592
2593#if QT_CONFIG(raster_fp)
2594static inline float color_dodge_op_rgbafp(float dst, float src, float da, float sa)
2595{
2596 const float sa_da = sa * da;
2597 const float dst_sa = dst * sa;
2598 const float src_da = src * da;
2599
2600 const float temp = src * (1.0f - da) + dst * (1.0f - sa);
2601 if (src_da + dst_sa > sa_da)
2602 return sa_da + temp;
2603 else if (src == sa || sa == 0.0f)
2604 return temp;
2605 else
2606 return dst_sa / (1.0f - src / sa) + temp;
2607}
2608
2609template <typename T>
2610static inline void comp_func_solid_ColorDodge_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
2611{
2612 float sa = color.alpha();
2613 float sr = color.red();
2614 float sg = color.green();
2615 float sb = color.blue();
2616
2617 for (int i = 0; i < length; ++i) {
2618 QRgbaFloat32 d = dest[i];
2619 float da = d.alpha();
2620
2621#define OP(a,b) color_dodge_op_rgbafp(a, b, da, sa)
2622 float r = OP( d.red(), sr);
2623 float b = OP( d.blue(), sb);
2624 float g = OP(d.green(), sg);
2625 float a = mix_alpha_rgbafp(da, sa);
2626#undef OP
2627
2628 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2629 }
2630}
2631
2632void QT_FASTCALL comp_func_solid_ColorDodge_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
2633{
2634 if (const_alpha == 255)
2635 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QFullCoverage());
2636 else
2637 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2638}
2639#endif
2640
2641template <typename T>
2642static inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2643{
2644 for (int i = 0; i < length; ++i) {
2645 uint d = dest[i];
2646 uint s = src[i];
2647
2648 int da = qAlpha(rgb: d);
2649 int sa = qAlpha(rgb: s);
2650
2651#define OP(a, b) color_dodge_op(a, b, da, sa)
2652 int r = OP( qRed(d), qRed(s));
2653 int b = OP( qBlue(d), qBlue(s));
2654 int g = OP(qGreen(d), qGreen(s));
2655 int a = mix_alpha(da, sa);
2656#undef OP
2657
2658 coverage.store(&dest[i], qRgba(r, g, b, a));
2659 }
2660}
2661
2662void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2663{
2664 if (const_alpha == 255)
2665 comp_func_ColorDodge_impl(dest, src, length, coverage: QFullCoverage());
2666 else
2667 comp_func_ColorDodge_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2668}
2669
2670#if QT_CONFIG(raster_64bit)
2671template <typename T>
2672static inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2673{
2674 for (int i = 0; i < length; ++i) {
2675 QRgba64 d = dest[i];
2676 QRgba64 s = src[i];
2677
2678 uint da = d.alpha();
2679 uint sa = s.alpha();
2680
2681#define OP(a, b) color_dodge_op_rgb64(a, b, da, sa)
2682 uint r = OP( d.red(), s.red());
2683 uint b = OP( d.blue(), s.blue());
2684 uint g = OP(d.green(), s.green());
2685 uint a = mix_alpha_rgb64(da, sa);
2686#undef OP
2687
2688 coverage.store(&dest[i], qRgba64(r, g, b, a));
2689 }
2690}
2691
2692void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2693{
2694 if (const_alpha == 255)
2695 comp_func_ColorDodge_impl(dest, src, length, coverage: QFullCoverage());
2696 else
2697 comp_func_ColorDodge_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2698}
2699#endif
2700
2701#if QT_CONFIG(raster_fp)
2702template <typename T>
2703static inline void comp_func_ColorDodge_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
2704{
2705 for (int i = 0; i < length; ++i) {
2706 QRgbaFloat32 d = dest[i];
2707 QRgbaFloat32 s = src[i];
2708
2709 float da = d.alpha();
2710 float sa = s.alpha();
2711
2712#define OP(a, b) color_dodge_op_rgbafp(a, b, da, sa)
2713 float r = OP( d.red(), s.red());
2714 float b = OP( d.blue(), s.blue());
2715 float g = OP(d.green(), s.green());
2716 float a = mix_alpha_rgbafp(da, sa);
2717#undef OP
2718
2719 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2720 }
2721}
2722
2723void QT_FASTCALL comp_func_ColorDodge_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2724{
2725 if (const_alpha == 255)
2726 comp_func_ColorDodge_impl(dest, src, length, coverage: QFullCoverage());
2727 else
2728 comp_func_ColorDodge_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2729}
2730#endif
2731
2732/*
2733 if Sca.Da + Dca.Sa < Sa.Da
2734 Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
2735 else if Sca == 0
2736 Dca' = Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
2737 otherwise
2738 Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
2739*/
2740static inline int color_burn_op(int dst, int src, int da, int sa)
2741{
2742 const int src_da = src * da;
2743 const int dst_sa = dst * sa;
2744 const int sa_da = sa * da;
2745
2746 const int temp = src * (255 - da) + dst * (255 - sa);
2747
2748 if (src_da + dst_sa < sa_da)
2749 return qt_div_255(x: temp);
2750 else if (src == 0)
2751 return qt_div_255(x: dst_sa + temp);
2752 return qt_div_255(x: sa * (src_da + dst_sa - sa_da) / src + temp);
2753}
2754
2755template <typename T>
2756static inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
2757{
2758 int sa = qAlpha(rgb: color);
2759 int sr = qRed(rgb: color);
2760 int sg = qGreen(rgb: color);
2761 int sb = qBlue(rgb: color);
2762
2763 for (int i = 0; i < length; ++i) {
2764 uint d = dest[i];
2765 int da = qAlpha(rgb: d);
2766
2767#define OP(a, b) color_burn_op(a, b, da, sa)
2768 int r = OP( qRed(d), sr);
2769 int b = OP( qBlue(d), sb);
2770 int g = OP(qGreen(d), sg);
2771 int a = mix_alpha(da, sa);
2772#undef OP
2773
2774 coverage.store(&dest[i], qRgba(r, g, b, a));
2775 }
2776}
2777
2778void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
2779{
2780 if (const_alpha == 255)
2781 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QFullCoverage());
2782 else
2783 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2784}
2785
2786#if QT_CONFIG(raster_64bit)
2787static inline uint color_burn_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
2788{
2789 const qint64 src_da = src * da;
2790 const qint64 dst_sa = dst * sa;
2791 const qint64 sa_da = sa * da;
2792
2793 const qint64 temp = src * (65535U - da) + dst * (65535U - sa);
2794
2795 if (src_da + dst_sa < sa_da)
2796 return qt_div_65535(x: temp);
2797 else if (src == 0)
2798 return qt_div_65535(x: dst_sa + temp);
2799 return qt_div_65535(x: sa * (src_da + dst_sa - sa_da) / src + temp);
2800}
2801
2802template <typename T>
2803static inline void comp_func_solid_ColorBurn_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2804{
2805 uint sa = color.alpha();
2806 uint sr = color.red();
2807 uint sg = color.green();
2808 uint sb = color.blue();
2809
2810 for (int i = 0; i < length; ++i) {
2811 QRgba64 d = dest[i];
2812 uint da = d.alpha();
2813
2814#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
2815 uint r = OP( d.red(), sr);
2816 uint b = OP( d.blue(), sb);
2817 uint g = OP(d.green(), sg);
2818 uint a = mix_alpha_rgb64(da, sa);
2819#undef OP
2820
2821 coverage.store(&dest[i], qRgba64(r, g, b, a));
2822 }
2823}
2824
2825void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2826{
2827 if (const_alpha == 255)
2828 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QFullCoverage());
2829 else
2830 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2831}
2832#endif
2833
2834#if QT_CONFIG(raster_fp)
2835static inline float color_burn_op_rgbafp(float dst, float src, float da, float sa)
2836{
2837 const float src_da = src * da;
2838 const float dst_sa = dst * sa;
2839 const float sa_da = sa * da;
2840
2841 const float temp = src * (1.0f - da) + dst * (1.0f - sa);
2842
2843 if (src_da + dst_sa < sa_da)
2844 return temp;
2845 else if (src == 0)
2846 return dst_sa + temp;
2847 return sa * (src_da + dst_sa - sa_da) / src + temp;
2848}
2849
2850template <typename T>
2851static inline void comp_func_solid_ColorBurn_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
2852{
2853 float sa = color.alpha();
2854 float sr = color.red();
2855 float sg = color.green();
2856 float sb = color.blue();
2857
2858 for (int i = 0; i < length; ++i) {
2859 QRgbaFloat32 d = dest[i];
2860 float da = d.alpha();
2861
2862#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa)
2863 float r = OP( d.red(), sr);
2864 float b = OP( d.blue(), sb);
2865 float g = OP(d.green(), sg);
2866 float a = mix_alpha_rgbafp(da, sa);
2867#undef OP
2868
2869 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2870 }
2871}
2872
2873void QT_FASTCALL comp_func_solid_ColorBurn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
2874{
2875 if (const_alpha == 255)
2876 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QFullCoverage());
2877 else
2878 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2879}
2880#endif
2881
2882template <typename T>
2883static inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2884{
2885 for (int i = 0; i < length; ++i) {
2886 uint d = dest[i];
2887 uint s = src[i];
2888
2889 int da = qAlpha(rgb: d);
2890 int sa = qAlpha(rgb: s);
2891
2892#define OP(a, b) color_burn_op(a, b, da, sa)
2893 int r = OP( qRed(d), qRed(s));
2894 int b = OP( qBlue(d), qBlue(s));
2895 int g = OP(qGreen(d), qGreen(s));
2896 int a = mix_alpha(da, sa);
2897#undef OP
2898
2899 coverage.store(&dest[i], qRgba(r, g, b, a));
2900 }
2901}
2902
2903void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2904{
2905 if (const_alpha == 255)
2906 comp_func_ColorBurn_impl(dest, src, length, coverage: QFullCoverage());
2907 else
2908 comp_func_ColorBurn_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2909}
2910
2911#if QT_CONFIG(raster_64bit)
2912template <typename T>
2913static inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2914{
2915 for (int i = 0; i < length; ++i) {
2916 QRgba64 d = dest[i];
2917 QRgba64 s = src[i];
2918
2919 uint da = d.alpha();
2920 uint sa = s.alpha();
2921
2922#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
2923 uint r = OP( d.red(), s.red());
2924 uint b = OP( d.blue(), s.blue());
2925 uint g = OP(d.green(), s.green());
2926 uint a = mix_alpha_rgb64(da, sa);
2927#undef OP
2928
2929 coverage.store(&dest[i], qRgba64(r, g, b, a));
2930 }
2931}
2932
2933void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2934{
2935 if (const_alpha == 255)
2936 comp_func_ColorBurn_impl(dest, src, length, coverage: QFullCoverage());
2937 else
2938 comp_func_ColorBurn_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2939}
2940#endif
2941
2942#if QT_CONFIG(raster_fp)
2943template <typename T>
2944static inline void comp_func_ColorBurn_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
2945{
2946 for (int i = 0; i < length; ++i) {
2947 QRgbaFloat32 d = dest[i];
2948 QRgbaFloat32 s = src[i];
2949
2950 float da = d.alpha();
2951 float sa = s.alpha();
2952
2953#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa)
2954 float r = OP( d.red(), s.red());
2955 float b = OP( d.blue(), s.blue());
2956 float g = OP(d.green(), s.green());
2957 float a = mix_alpha_rgbafp(da, sa);
2958#undef OP
2959
2960 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
2961 }
2962}
2963
2964void QT_FASTCALL comp_func_ColorBurn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2965{
2966 if (const_alpha == 255)
2967 comp_func_ColorBurn_impl(dest, src, length, coverage: QFullCoverage());
2968 else
2969 comp_func_ColorBurn_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2970}
2971#endif
2972
2973/*
2974 if 2.Sca < Sa
2975 Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
2976 otherwise
2977 Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
2978*/
2979static inline uint hardlight_op(int dst, int src, int da, int sa)
2980{
2981 const uint temp = src * (255 - da) + dst * (255 - sa);
2982
2983 if (2 * src < sa)
2984 return qt_div_255(x: 2 * src * dst + temp);
2985 else
2986 return qt_div_255(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
2987}
2988
2989template <typename T>
2990static inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
2991{
2992 int sa = qAlpha(rgb: color);
2993 int sr = qRed(rgb: color);
2994 int sg = qGreen(rgb: color);
2995 int sb = qBlue(rgb: color);
2996
2997 for (int i = 0; i < length; ++i) {
2998 uint d = dest[i];
2999 int da = qAlpha(rgb: d);
3000
3001#define OP(a, b) hardlight_op(a, b, da, sa)
3002 int r = OP( qRed(d), sr);
3003 int b = OP( qBlue(d), sb);
3004 int g = OP(qGreen(d), sg);
3005 int a = mix_alpha(da, sa);
3006#undef OP
3007
3008 coverage.store(&dest[i], qRgba(r, g, b, a));
3009 }
3010}
3011
3012void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
3013{
3014 if (const_alpha == 255)
3015 comp_func_solid_HardLight_impl(dest, length, color, coverage: QFullCoverage());
3016 else
3017 comp_func_solid_HardLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3018}
3019
3020#if QT_CONFIG(raster_64bit)
3021static inline uint hardlight_op_rgb64(uint dst, uint src, uint da, uint sa)
3022{
3023 const uint temp = src * (65535U - da) + dst * (65535U - sa);
3024
3025 if (2 * src < sa)
3026 return qt_div_65535(x: 2 * src * dst + temp);
3027 else
3028 return qt_div_65535(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
3029}
3030
3031template <typename T>
3032static inline void comp_func_solid_HardLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
3033{
3034 uint sa = color.alpha();
3035 uint sr = color.red();
3036 uint sg = color.green();
3037 uint sb = color.blue();
3038
3039 for (int i = 0; i < length; ++i) {
3040 QRgba64 d = dest[i];
3041 uint da = d.alpha();
3042
3043#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
3044 uint r = OP( d.red(), sr);
3045 uint b = OP( d.blue(), sb);
3046 uint g = OP(d.green(), sg);
3047 uint a = mix_alpha_rgb64(da, sa);
3048#undef OP
3049
3050 coverage.store(&dest[i], qRgba64(r, g, b, a));
3051 }
3052}
3053
3054void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
3055{
3056 if (const_alpha == 255)
3057 comp_func_solid_HardLight_impl(dest, length, color, coverage: QFullCoverage());
3058 else
3059 comp_func_solid_HardLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3060}
3061#endif
3062
3063#if QT_CONFIG(raster_fp)
3064static inline float hardlight_op_rgbafp(float dst, float src, float da, float sa)
3065{
3066 const float temp = src * (1.0f - da) + dst * (1.0f - sa);
3067
3068 if (2 * src < sa)
3069 return 2 * src * dst + temp;
3070 else
3071 return sa * da - 2 * (da - dst) * (sa - src) + temp;
3072}
3073
3074template <typename T>
3075static inline void comp_func_solid_HardLight_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
3076{
3077 float sa = color.alpha();
3078 float sr = color.red();
3079 float sg = color.green();
3080 float sb = color.blue();
3081
3082 for (int i = 0; i < length; ++i) {
3083 QRgbaFloat32 d = dest[i];
3084 float da = d.alpha();
3085
3086#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa)
3087 float r = OP( d.red(), sr);
3088 float b = OP( d.blue(), sb);
3089 float g = OP(d.green(), sg);
3090 float a = mix_alpha_rgbafp(da, sa);
3091#undef OP
3092
3093 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3094 }
3095}
3096
3097void QT_FASTCALL comp_func_solid_HardLight_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
3098{
3099 if (const_alpha == 255)
3100 comp_func_solid_HardLight_impl(dest, length, color, coverage: QFullCoverage());
3101 else
3102 comp_func_solid_HardLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3103}
3104#endif
3105
3106template <typename T>
3107static inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
3108{
3109 for (int i = 0; i < length; ++i) {
3110 uint d = dest[i];
3111 uint s = src[i];
3112
3113 int da = qAlpha(rgb: d);
3114 int sa = qAlpha(rgb: s);
3115
3116#define OP(a, b) hardlight_op(a, b, da, sa)
3117 int r = OP( qRed(d), qRed(s));
3118 int b = OP( qBlue(d), qBlue(s));
3119 int g = OP(qGreen(d), qGreen(s));
3120 int a = mix_alpha(da, sa);
3121#undef OP
3122
3123 coverage.store(&dest[i], qRgba(r, g, b, a));
3124 }
3125}
3126
3127void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
3128{
3129 if (const_alpha == 255)
3130 comp_func_HardLight_impl(dest, src, length, coverage: QFullCoverage());
3131 else
3132 comp_func_HardLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3133}
3134
3135#if QT_CONFIG(raster_64bit)
3136template <typename T>
3137static inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
3138{
3139 for (int i = 0; i < length; ++i) {
3140 QRgba64 d = dest[i];
3141 QRgba64 s = src[i];
3142
3143 uint da = d.alpha();
3144 uint sa = s.alpha();
3145
3146#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
3147 uint r = OP( d.red(), s.red());
3148 uint b = OP( d.blue(), s.blue());
3149 uint g = OP(d.green(), s.green());
3150 uint a = mix_alpha_rgb64(da, sa);
3151#undef OP
3152
3153 coverage.store(&dest[i], qRgba64(r, g, b, a));
3154 }
3155}
3156
3157void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3158{
3159 if (const_alpha == 255)
3160 comp_func_HardLight_impl(dest, src, length, coverage: QFullCoverage());
3161 else
3162 comp_func_HardLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3163}
3164#endif
3165
3166#if QT_CONFIG(raster_fp)
3167template <typename T>
3168static inline void comp_func_HardLight_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
3169{
3170 for (int i = 0; i < length; ++i) {
3171 QRgbaFloat32 d = dest[i];
3172 QRgbaFloat32 s = src[i];
3173
3174 float da = d.alpha();
3175 float sa = s.alpha();
3176
3177#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa)
3178 float r = OP( d.red(), s.red());
3179 float b = OP( d.blue(), s.blue());
3180 float g = OP(d.green(), s.green());
3181 float a = mix_alpha_rgbafp(da, sa);
3182#undef OP
3183
3184 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3185 }
3186}
3187
3188void QT_FASTCALL comp_func_HardLight_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3189{
3190 if (const_alpha == 255)
3191 comp_func_HardLight_impl(dest, src, length, coverage: QFullCoverage());
3192 else
3193 comp_func_HardLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3194}
3195#endif
3196
3197/*
3198 if 2.Sca <= Sa
3199 Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
3200 otherwise if 2.Sca > Sa and 4.Dca <= Da
3201 Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
3202 otherwise if 2.Sca > Sa and 4.Dca > Da
3203 Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
3204*/
3205static inline int soft_light_op(int dst, int src, int da, int sa)
3206{
3207 const int src2 = src << 1;
3208 const int dst_np = da != 0 ? (255 * dst) / da : 0;
3209 const int temp = (src * (255 - da) + dst * (255 - sa)) * 255;
3210
3211 if (src2 < sa)
3212 return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025;
3213 else if (4 * dst <= da)
3214 return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
3215 else {
3216 return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(v: qreal(dst_np * 255))) - dst_np) + temp) / 65025;
3217 }
3218}
3219
3220template <typename T>
3221static inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
3222{
3223 int sa = qAlpha(rgb: color);
3224 int sr = qRed(rgb: color);
3225 int sg = qGreen(rgb: color);
3226 int sb = qBlue(rgb: color);
3227
3228 for (int i = 0; i < length; ++i) {
3229 uint d = dest[i];
3230 int da = qAlpha(rgb: d);
3231
3232#define OP(a, b) soft_light_op(a, b, da, sa)
3233 int r = OP( qRed(d), sr);
3234 int b = OP( qBlue(d), sb);
3235 int g = OP(qGreen(d), sg);
3236 int a = mix_alpha(da, sa);
3237#undef OP
3238
3239 coverage.store(&dest[i], qRgba(r, g, b, a));
3240 }
3241}
3242
3243void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
3244{
3245 if (const_alpha == 255)
3246 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QFullCoverage());
3247 else
3248 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3249}
3250
3251#if QT_CONFIG(raster_64bit)
3252static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
3253{
3254 const qint64 src2 = src << 1;
3255 const qint64 dst_np = da != 0 ? (65535U * dst) / da : 0;
3256 const qint64 temp = (src * (65535U - da) + dst * (65535U - sa)) * 65535U;
3257 const qint64 factor = Q_UINT64_C(65535) * 65535U;
3258
3259 if (src2 < sa)
3260 return (dst * (sa * 65535U + (src2 - sa) * (65535U - dst_np)) + temp) / factor;
3261 else if (4 * dst <= da)
3262 return (dst * sa * 65535U + da * (src2 - sa) * ((((16 * dst_np - 12 * 65535U) * dst_np + 3 * factor) * dst_np) / factor) + temp) / factor;
3263 else {
3264 return (dst * sa * 65535U + da * (src2 - sa) * (int(qSqrt(v: qreal(dst_np * 65535U))) - dst_np) + temp) / factor;
3265 }
3266}
3267
3268template <typename T>
3269static inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
3270{
3271 uint sa = color.alpha();
3272 uint sr = color.red();
3273 uint sg = color.green();
3274 uint sb = color.blue();
3275
3276 for (int i = 0; i < length; ++i) {
3277 QRgba64 d = dest[i];
3278 uint da = d.alpha();
3279
3280#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
3281 uint r = OP( d.red(), sr);
3282 uint b = OP( d.blue(), sb);
3283 uint g = OP(d.green(), sg);
3284 uint a = mix_alpha_rgb64(da, sa);
3285#undef OP
3286
3287 coverage.store(&dest[i], qRgba64(r, g, b, a));
3288 }
3289}
3290
3291void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
3292{
3293 if (const_alpha == 255)
3294 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QFullCoverage());
3295 else
3296 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3297}
3298
3299#endif
3300
3301#if QT_CONFIG(raster_fp)
3302static inline float soft_light_op_rgbafp(float dst, float src, float da, float sa)
3303{
3304 const float src2 = src * 2;
3305 const float dst_np = da != 0.0f ? (dst / da) : 0.0f;
3306 const float temp = src * (1.0f - da) + dst * (1.0f - sa);
3307
3308 if (src2 < sa)
3309 return dst * (sa + (src2 - sa) * (1.0f - dst_np)) + temp;
3310 else if (4 * dst <= da)
3311 return dst * sa + da * (src2 - sa) * (((16 * dst_np - 12) * dst_np + 3) * dst_np) + temp;
3312 else {
3313 return dst * sa + da * (src2 - sa) * (qSqrt(v: qreal(dst_np)) - dst_np) + temp;
3314 }
3315}
3316
3317template <typename T>
3318static inline void comp_func_solid_SoftLight_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
3319{
3320 float sa = color.alpha();
3321 float sr = color.red();
3322 float sg = color.green();
3323 float sb = color.blue();
3324
3325 for (int i = 0; i < length; ++i) {
3326 QRgbaFloat32 d = dest[i];
3327 float da = d.alpha();
3328
3329#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa)
3330 float r = OP( d.red(), sr);
3331 float b = OP( d.blue(), sb);
3332 float g = OP(d.green(), sg);
3333 float a = mix_alpha_rgbafp(da, sa);
3334#undef OP
3335
3336 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3337 }
3338}
3339
3340void QT_FASTCALL comp_func_solid_SoftLight_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
3341{
3342 if (const_alpha == 255)
3343 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QFullCoverage());
3344 else
3345 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3346}
3347#endif
3348
3349template <typename T>
3350static inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
3351{
3352 for (int i = 0; i < length; ++i) {
3353 uint d = dest[i];
3354 uint s = src[i];
3355
3356 int da = qAlpha(rgb: d);
3357 int sa = qAlpha(rgb: s);
3358
3359#define OP(a, b) soft_light_op(a, b, da, sa)
3360 int r = OP( qRed(d), qRed(s));
3361 int b = OP( qBlue(d), qBlue(s));
3362 int g = OP(qGreen(d), qGreen(s));
3363 int a = mix_alpha(da, sa);
3364#undef OP
3365
3366 coverage.store(&dest[i], qRgba(r, g, b, a));
3367 }
3368}
3369
3370void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
3371{
3372 if (const_alpha == 255)
3373 comp_func_SoftLight_impl(dest, src, length, coverage: QFullCoverage());
3374 else
3375 comp_func_SoftLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3376}
3377
3378#if QT_CONFIG(raster_64bit)
3379template <typename T>
3380static inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
3381{
3382 for (int i = 0; i < length; ++i) {
3383 QRgba64 d = dest[i];
3384 QRgba64 s = src[i];
3385
3386 uint da = d.alpha();
3387 uint sa = s.alpha();
3388
3389#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
3390 uint r = OP( d.red(), s.red());
3391 uint b = OP( d.blue(), s.blue());
3392 uint g = OP(d.green(), s.green());
3393 uint a = mix_alpha_rgb64(da, sa);
3394#undef OP
3395
3396 coverage.store(&dest[i], qRgba64(r, g, b, a));
3397 }
3398}
3399
3400void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3401{
3402 if (const_alpha == 255)
3403 comp_func_SoftLight_impl(dest, src, length, coverage: QFullCoverage());
3404 else
3405 comp_func_SoftLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3406}
3407#endif
3408
3409#if QT_CONFIG(raster_fp)
3410template <typename T>
3411static inline void comp_func_SoftLight_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
3412{
3413 for (int i = 0; i < length; ++i) {
3414 QRgbaFloat32 d = dest[i];
3415 QRgbaFloat32 s = src[i];
3416
3417 float da = d.alpha();
3418 float sa = s.alpha();
3419
3420#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa)
3421 float r = OP( d.red(), s.red());
3422 float b = OP( d.blue(), s.blue());
3423 float g = OP(d.green(), s.green());
3424 float a = mix_alpha_rgbafp(da, sa);
3425#undef OP
3426
3427 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3428 }
3429}
3430
3431void QT_FASTCALL comp_func_SoftLight_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3432{
3433 if (const_alpha == 255)
3434 comp_func_SoftLight_impl(dest, src, length, coverage: QFullCoverage());
3435 else
3436 comp_func_SoftLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3437}
3438#endif
3439
3440/*
3441 Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
3442 = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
3443*/
3444static inline int difference_op(int dst, int src, int da, int sa)
3445{
3446 return src + dst - qt_div_255(x: 2 * qMin(a: src * da, b: dst * sa));
3447}
3448
3449template <typename T>
3450static inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
3451{
3452 int sa = qAlpha(rgb: color);
3453 int sr = qRed(rgb: color);
3454 int sg = qGreen(rgb: color);
3455 int sb = qBlue(rgb: color);
3456
3457 for (int i = 0; i < length; ++i) {
3458 uint d = dest[i];
3459 int da = qAlpha(rgb: d);
3460
3461#define OP(a, b) difference_op(a, b, da, sa)
3462 int r = OP( qRed(d), sr);
3463 int b = OP( qBlue(d), sb);
3464 int g = OP(qGreen(d), sg);
3465 int a = mix_alpha(da, sa);
3466#undef OP
3467
3468 coverage.store(&dest[i], qRgba(r, g, b, a));
3469 }
3470}
3471
3472void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
3473{
3474 if (const_alpha == 255)
3475 comp_func_solid_Difference_impl(dest, length, color, coverage: QFullCoverage());
3476 else
3477 comp_func_solid_Difference_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3478}
3479
3480#if QT_CONFIG(raster_64bit)
3481static inline uint difference_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
3482{
3483 return src + dst - qt_div_65535(x: 2 * qMin(a: src * da, b: dst * sa));
3484}
3485
3486template <typename T>
3487static inline void comp_func_solid_Difference_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
3488{
3489 uint sa = color.alpha();
3490 uint sr = color.red();
3491 uint sg = color.green();
3492 uint sb = color.blue();
3493
3494 for (int i = 0; i < length; ++i) {
3495 QRgba64 d = dest[i];
3496 uint da = d.alpha();
3497
3498#define OP(a, b) difference_op_rgb64(a, b, da, sa)
3499 uint r = OP( d.red(), sr);
3500 uint b = OP( d.blue(), sb);
3501 uint g = OP(d.green(), sg);
3502 uint a = mix_alpha_rgb64(da, sa);
3503#undef OP
3504
3505 coverage.store(&dest[i], qRgba64(r, g, b, a));
3506 }
3507}
3508
3509void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
3510{
3511 if (const_alpha == 255)
3512 comp_func_solid_Difference_impl(dest, length, color, coverage: QFullCoverage());
3513 else
3514 comp_func_solid_Difference_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3515}
3516#endif
3517
3518#if QT_CONFIG(raster_fp)
3519static inline float difference_op_rgbafp(float dst, float src, float da, float sa)
3520{
3521 return src + dst - (2 * qMin(a: src * da, b: dst * sa));
3522}
3523
3524template <typename T>
3525static inline void comp_func_solid_Difference_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
3526{
3527 float sa = color.alpha();
3528 float sr = color.red();
3529 float sg = color.green();
3530 float sb = color.blue();
3531
3532 for (int i = 0; i < length; ++i) {
3533 QRgbaFloat32 d = dest[i];
3534 float da = d.alpha();
3535
3536#define OP(a, b) difference_op_rgbafp(a, b, da, sa)
3537 float r = OP( d.red(), sr);
3538 float b = OP( d.blue(), sb);
3539 float g = OP(d.green(), sg);
3540 float a = mix_alpha_rgbafp(da, sa);
3541#undef OP
3542
3543 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3544 }
3545}
3546
3547void QT_FASTCALL comp_func_solid_Difference_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
3548{
3549 if (const_alpha == 255)
3550 comp_func_solid_Difference_impl(dest, length, color, coverage: QFullCoverage());
3551 else
3552 comp_func_solid_Difference_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3553}
3554#endif
3555
3556template <typename T>
3557static inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
3558{
3559 for (int i = 0; i < length; ++i) {
3560 uint d = dest[i];
3561 uint s = src[i];
3562
3563 int da = qAlpha(rgb: d);
3564 int sa = qAlpha(rgb: s);
3565
3566#define OP(a, b) difference_op(a, b, da, sa)
3567 int r = OP( qRed(d), qRed(s));
3568 int b = OP( qBlue(d), qBlue(s));
3569 int g = OP(qGreen(d), qGreen(s));
3570 int a = mix_alpha(da, sa);
3571#undef OP
3572
3573 coverage.store(&dest[i], qRgba(r, g, b, a));
3574 }
3575}
3576
3577void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
3578{
3579 if (const_alpha == 255)
3580 comp_func_Difference_impl(dest, src, length, coverage: QFullCoverage());
3581 else
3582 comp_func_Difference_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3583}
3584
3585#if QT_CONFIG(raster_64bit)
3586template <typename T>
3587static inline void comp_func_Difference_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
3588{
3589 for (int i = 0; i < length; ++i) {
3590 QRgba64 d = dest[i];
3591 QRgba64 s = src[i];
3592
3593 uint da = d.alpha();
3594 uint sa = s.alpha();
3595
3596#define OP(a, b) difference_op_rgb64(a, b, da, sa)
3597 uint r = OP( d.red(), s.red());
3598 uint b = OP( d.blue(), s.blue());
3599 uint g = OP(d.green(), s.green());
3600 uint a = mix_alpha_rgb64(da, sa);
3601#undef OP
3602
3603 coverage.store(&dest[i], qRgba64(r, g, b, a));
3604 }
3605}
3606
3607void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3608{
3609 if (const_alpha == 255)
3610 comp_func_Difference_impl(dest, src, length, coverage: QFullCoverage());
3611 else
3612 comp_func_Difference_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3613}
3614#endif
3615
3616#if QT_CONFIG(raster_fp)
3617template <typename T>
3618static inline void comp_func_Difference_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
3619{
3620 for (int i = 0; i < length; ++i) {
3621 QRgbaFloat32 d = dest[i];
3622 QRgbaFloat32 s = src[i];
3623
3624 float da = d.alpha();
3625 float sa = s.alpha();
3626
3627#define OP(a, b) difference_op_rgbafp(a, b, da, sa)
3628 float r = OP( d.red(), s.red());
3629 float b = OP( d.blue(), s.blue());
3630 float g = OP(d.green(), s.green());
3631 float a = mix_alpha_rgbafp(da, sa);
3632#undef OP
3633
3634 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3635 }
3636}
3637
3638void QT_FASTCALL comp_func_Difference_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3639{
3640 if (const_alpha == 255)
3641 comp_func_Difference_impl(dest, src, length, coverage: QFullCoverage());
3642 else
3643 comp_func_Difference_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3644}
3645#endif
3646
3647/*
3648 Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
3649*/
3650template <typename T>
3651static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
3652{
3653 int sa = qAlpha(rgb: color);
3654 int sr = qRed(rgb: color);
3655 int sg = qGreen(rgb: color);
3656 int sb = qBlue(rgb: color);
3657
3658 for (int i = 0; i < length; ++i) {
3659 uint d = dest[i];
3660 int da = qAlpha(rgb: d);
3661
3662#define OP(a, b) (a + b - qt_div_255(2*(a*b)))
3663 int r = OP( qRed(d), sr);
3664 int b = OP( qBlue(d), sb);
3665 int g = OP(qGreen(d), sg);
3666 int a = mix_alpha(da, sa);
3667#undef OP
3668
3669 coverage.store(&dest[i], qRgba(r, g, b, a));
3670 }
3671}
3672
3673void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
3674{
3675 if (const_alpha == 255)
3676 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QFullCoverage());
3677 else
3678 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3679}
3680
3681#if QT_CONFIG(raster_64bit)
3682template <typename T>
3683static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
3684{
3685 uint sa = color.alpha();
3686 uint sr = color.red();
3687 uint sg = color.green();
3688 uint sb = color.blue();
3689
3690 for (int i = 0; i < length; ++i) {
3691 QRgba64 d = dest[i];
3692 uint da = d.alpha();
3693
3694#define OP(a, b) (a + b - qt_div_65535(2*(qint64(a)*b)))
3695 uint r = OP( d.red(), sr);
3696 uint b = OP( d.blue(), sb);
3697 uint g = OP(d.green(), sg);
3698 uint a = mix_alpha_rgb64(da, sa);
3699#undef OP
3700
3701 coverage.store(&dest[i], qRgba64(r, g, b, a));
3702 }
3703}
3704
3705void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
3706{
3707 if (const_alpha == 255)
3708 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QFullCoverage());
3709 else
3710 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3711}
3712#endif
3713
3714#if QT_CONFIG(raster_fp)
3715template <typename T>
3716static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage)
3717{
3718 float sa = color.alpha();
3719 float sr = color.red();
3720 float sg = color.green();
3721 float sb = color.blue();
3722
3723 for (int i = 0; i < length; ++i) {
3724 QRgbaFloat32 d = dest[i];
3725 float da = d.alpha();
3726
3727#define OP(a, b) (a + b - (2.0f * a * b))
3728 float r = OP( d.red(), sr);
3729 float b = OP( d.blue(), sb);
3730 float g = OP(d.green(), sg);
3731 float a = mix_alpha_rgbafp(da, sa);
3732#undef OP
3733
3734 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3735 }
3736}
3737
3738void QT_FASTCALL comp_func_solid_Exclusion_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha)
3739{
3740 if (const_alpha == 255)
3741 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QFullCoverage());
3742 else
3743 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
3744}
3745#endif
3746
3747template <typename T>
3748static inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
3749{
3750 for (int i = 0; i < length; ++i) {
3751 uint d = dest[i];
3752 uint s = src[i];
3753
3754 int da = qAlpha(rgb: d);
3755 int sa = qAlpha(rgb: s);
3756
3757#define OP(a, b) (a + b - ((a*b) >> 7))
3758 int r = OP( qRed(d), qRed(s));
3759 int b = OP( qBlue(d), qBlue(s));
3760 int g = OP(qGreen(d), qGreen(s));
3761 int a = mix_alpha(da, sa);
3762#undef OP
3763
3764 coverage.store(&dest[i], qRgba(r, g, b, a));
3765 }
3766}
3767
3768void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
3769{
3770 if (const_alpha == 255)
3771 comp_func_Exclusion_impl(dest, src, length, coverage: QFullCoverage());
3772 else
3773 comp_func_Exclusion_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3774}
3775
3776#if QT_CONFIG(raster_64bit)
3777template <typename T>
3778static inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
3779{
3780 for (int i = 0; i < length; ++i) {
3781 QRgba64 d = dest[i];
3782 QRgba64 s = src[i];
3783
3784 uint da = d.alpha();
3785 uint sa = s.alpha();
3786
3787#define OP(a, b) (a + b - ((qint64(a)*b) >> 15))
3788 uint r = OP( d.red(), s.red());
3789 uint b = OP( d.blue(), s.blue());
3790 uint g = OP(d.green(), s.green());
3791 uint a = mix_alpha_rgb64(da, sa);
3792#undef OP
3793
3794 coverage.store(&dest[i], qRgba64(r, g, b, a));
3795 }
3796}
3797
3798void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3799{
3800 if (const_alpha == 255)
3801 comp_func_Exclusion_impl(dest, src, length, coverage: QFullCoverage());
3802 else
3803 comp_func_Exclusion_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3804}
3805#endif
3806
3807#if QT_CONFIG(raster_fp)
3808template <typename T>
3809static inline void comp_func_Exclusion_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage)
3810{
3811 for (int i = 0; i < length; ++i) {
3812 QRgbaFloat32 d = dest[i];
3813 QRgbaFloat32 s = src[i];
3814
3815 float da = d.alpha();
3816 float sa = s.alpha();
3817
3818#define OP(a, b) (a + b - (2.0f * a * b))
3819 float r = OP( d.red(), s.red());
3820 float b = OP( d.blue(), s.blue());
3821 float g = OP(d.green(), s.green());
3822 float a = mix_alpha_rgbafp(da, sa);
3823#undef OP
3824
3825 coverage.store(&dest[i], qRgbaFloat32(r, g, b, a));
3826 }
3827}
3828
3829void QT_FASTCALL comp_func_Exclusion_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha)
3830{
3831 if (const_alpha == 255)
3832 comp_func_Exclusion_impl(dest, src, length, coverage: QFullCoverage());
3833 else
3834 comp_func_Exclusion_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
3835}
3836#endif
3837
3838void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
3839 int length,
3840 uint color,
3841 uint const_alpha)
3842{
3843 Q_UNUSED(const_alpha);
3844 while (length--)
3845 *dest++ |= color;
3846}
3847
3848void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest,
3849 const uint *Q_DECL_RESTRICT src,
3850 int length,
3851 uint const_alpha)
3852{
3853 Q_UNUSED(const_alpha);
3854 while (length--)
3855 *dest++ |= *src++;
3856}
3857
3858void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
3859 int length,
3860 uint color,
3861 uint const_alpha)
3862{
3863 Q_UNUSED(const_alpha);
3864 color |= 0xff000000;
3865 while (length--)
3866 *dest++ &= color;
3867}
3868
3869void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest,
3870 const uint *Q_DECL_RESTRICT src,
3871 int length,
3872 uint const_alpha)
3873{
3874 Q_UNUSED(const_alpha);
3875 while (length--) {
3876 *dest = (*src & *dest) | 0xff000000;
3877 ++dest; ++src;
3878 }
3879}
3880
3881void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
3882 int length,
3883 uint color,
3884 uint const_alpha)
3885{
3886 Q_UNUSED(const_alpha);
3887 color &= 0x00ffffff;
3888 while (length--)
3889 *dest++ ^= color;
3890}
3891
3892void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest,
3893 const uint *Q_DECL_RESTRICT src,
3894 int length,
3895 uint const_alpha)
3896{
3897 Q_UNUSED(const_alpha);
3898 while (length--) {
3899 *dest = (*src ^ *dest) | 0xff000000;
3900 ++dest; ++src;
3901 }
3902}
3903
3904void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
3905 int length,
3906 uint color,
3907 uint const_alpha)
3908{
3909 Q_UNUSED(const_alpha);
3910 color = ~color;
3911 while (length--) {
3912 *dest = (color & ~(*dest)) | 0xff000000;
3913 ++dest;
3914 }
3915}
3916
3917void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
3918 const uint *Q_DECL_RESTRICT src,
3919 int length,
3920 uint const_alpha)
3921{
3922 Q_UNUSED(const_alpha);
3923 while (length--) {
3924 *dest = (~(*src) & ~(*dest)) | 0xff000000;
3925 ++dest; ++src;
3926 }
3927}
3928
3929void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
3930 int length,
3931 uint color,
3932 uint const_alpha)
3933{
3934 Q_UNUSED(const_alpha);
3935 color = ~color | 0xff000000;
3936 while (length--) {
3937 *dest = color | ~(*dest);
3938 ++dest;
3939 }
3940}
3941
3942void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
3943 const uint *Q_DECL_RESTRICT src,
3944 int length,
3945 uint const_alpha)
3946{
3947 Q_UNUSED(const_alpha);
3948 while (length--) {
3949 *dest = ~(*src) | ~(*dest) | 0xff000000;
3950 ++dest; ++src;
3951 }
3952}
3953
3954void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
3955 int length,
3956 uint color,
3957 uint const_alpha)
3958{
3959 Q_UNUSED(const_alpha);
3960 color = ~color & 0x00ffffff;
3961 while (length--) {
3962 *dest = color ^ (*dest);
3963 ++dest;
3964 }
3965}
3966
3967void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest,
3968 const uint *Q_DECL_RESTRICT src,
3969 int length,
3970 uint const_alpha)
3971{
3972 Q_UNUSED(const_alpha);
3973 while (length--) {
3974 *dest = ((~(*src)) ^ (*dest)) | 0xff000000;
3975 ++dest; ++src;
3976 }
3977}
3978
3979void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
3980 uint color, uint const_alpha)
3981{
3982 Q_UNUSED(const_alpha);
3983 qt_memfill(dest, color: ~color | 0xff000000, count: length);
3984}
3985
3986void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src,
3987 int length, uint const_alpha)
3988{
3989 Q_UNUSED(const_alpha);
3990 while (length--)
3991 *dest++ = ~(*src++) | 0xff000000;
3992}
3993
3994void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
3995 int length,
3996 uint color,
3997 uint const_alpha)
3998{
3999 Q_UNUSED(const_alpha);
4000 color = ~color | 0xff000000;
4001 while (length--) {
4002 *dest = color & *dest;
4003 ++dest;
4004 }
4005}
4006
4007void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest,
4008 const uint *Q_DECL_RESTRICT src,
4009 int length,
4010 uint const_alpha)
4011{
4012 Q_UNUSED(const_alpha);
4013 while (length--) {
4014 *dest = (~(*src) & *dest) | 0xff000000;
4015 ++dest; ++src;
4016 }
4017}
4018
4019void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
4020 int length,
4021 uint color,
4022 uint const_alpha)
4023{
4024 Q_UNUSED(const_alpha);
4025 while (length--) {
4026 *dest = (color & ~(*dest)) | 0xff000000;
4027 ++dest;
4028 }
4029}
4030
4031void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
4032 const uint *Q_DECL_RESTRICT src,
4033 int length,
4034 uint const_alpha)
4035{
4036 Q_UNUSED(const_alpha);
4037 while (length--) {
4038 *dest = (*src & ~(*dest)) | 0xff000000;
4039 ++dest; ++src;
4040 }
4041}
4042
4043void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
4044 const uint *Q_DECL_RESTRICT src,
4045 int length,
4046 uint const_alpha)
4047{
4048 Q_UNUSED(const_alpha);
4049 while (length--) {
4050 *dest = (~(*src) | *dest) | 0xff000000;
4051 ++dest; ++src;
4052 }
4053}
4054
4055void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
4056 int length,
4057 uint color,
4058 uint const_alpha)
4059{
4060 Q_UNUSED(const_alpha);
4061 color = ~color | 0xff000000;
4062 while (length--)
4063 *dest++ |= color;
4064}
4065
4066void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
4067 const uint *Q_DECL_RESTRICT src,
4068 int length,
4069 uint const_alpha)
4070{
4071 Q_UNUSED(const_alpha);
4072 while (length--) {
4073 *dest = (*src | ~(*dest)) | 0xff000000;
4074 ++dest; ++src;
4075 }
4076}
4077
4078void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
4079 int length,
4080 uint color,
4081 uint const_alpha)
4082{
4083 Q_UNUSED(const_alpha);
4084 while (length--) {
4085 *dest = (color | ~(*dest)) | 0xff000000;
4086 ++dest;
4087 }
4088}
4089
4090void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest,
4091 const uint *Q_DECL_RESTRICT src,
4092 int length,
4093 uint const_alpha)
4094{
4095 Q_UNUSED(src);
4096 comp_func_solid_SourceOver (dest, length, color: 0xff000000, const_alpha);
4097}
4098
4099void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest,
4100 int length,
4101 uint color,
4102 uint const_alpha)
4103{
4104 Q_UNUSED(color);
4105 comp_func_solid_SourceOver (dest, length, color: 0xff000000, const_alpha);
4106}
4107
4108void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest,
4109 const uint *Q_DECL_RESTRICT src,
4110 int length,
4111 uint const_alpha)
4112{
4113 Q_UNUSED(src);
4114 comp_func_solid_SourceOver (dest, length, color: 0xffffffff, const_alpha);
4115}
4116
4117void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest,
4118 int length,
4119 uint color,
4120 uint const_alpha)
4121{
4122 Q_UNUSED(color);
4123 comp_func_solid_SourceOver (dest, length, color: 0xffffffff, const_alpha);
4124}
4125
4126void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest,
4127 const uint *Q_DECL_RESTRICT src,
4128 int length,
4129 uint const_alpha)
4130{
4131 Q_UNUSED(src);
4132 rasterop_solid_SourceXorDestination (dest, length, color: 0x00ffffff, const_alpha);
4133}
4134
4135void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest,
4136 int length,
4137 uint color,
4138 uint const_alpha)
4139{
4140 Q_UNUSED(color);
4141 rasterop_solid_SourceXorDestination (dest, length, color: 0x00ffffff, const_alpha);
4142}
4143
4144CompositionFunctionSolid qt_functionForModeSolid_C[] = {
4145 comp_func_solid_SourceOver,
4146 comp_func_solid_DestinationOver,
4147 comp_func_solid_Clear,
4148 comp_func_solid_Source,
4149 comp_func_solid_Destination,
4150 comp_func_solid_SourceIn,
4151 comp_func_solid_DestinationIn,
4152 comp_func_solid_SourceOut,
4153 comp_func_solid_DestinationOut,
4154 comp_func_solid_SourceAtop,
4155 comp_func_solid_DestinationAtop,
4156 comp_func_solid_XOR,
4157 comp_func_solid_Plus,
4158 comp_func_solid_Multiply,
4159 comp_func_solid_Screen,
4160 comp_func_solid_Overlay,
4161 comp_func_solid_Darken,
4162 comp_func_solid_Lighten,
4163 comp_func_solid_ColorDodge,
4164 comp_func_solid_ColorBurn,
4165 comp_func_solid_HardLight,
4166 comp_func_solid_SoftLight,
4167 comp_func_solid_Difference,
4168 comp_func_solid_Exclusion,
4169 rasterop_solid_SourceOrDestination,
4170 rasterop_solid_SourceAndDestination,
4171 rasterop_solid_SourceXorDestination,
4172 rasterop_solid_NotSourceAndNotDestination,
4173 rasterop_solid_NotSourceOrNotDestination,
4174 rasterop_solid_NotSourceXorDestination,
4175 rasterop_solid_NotSource,
4176 rasterop_solid_NotSourceAndDestination,
4177 rasterop_solid_SourceAndNotDestination,
4178 rasterop_solid_NotSourceOrDestination,
4179 rasterop_solid_SourceOrNotDestination,
4180 rasterop_solid_ClearDestination,
4181 rasterop_solid_SetDestination,
4182 rasterop_solid_NotDestination
4183};
4184
4185CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
4186#if QT_CONFIG(raster_64bit)
4187 comp_func_solid_SourceOver_rgb64,
4188 comp_func_solid_DestinationOver_rgb64,
4189 comp_func_solid_Clear_rgb64,
4190 comp_func_solid_Source_rgb64,
4191 comp_func_solid_Destination_rgb64,
4192 comp_func_solid_SourceIn_rgb64,
4193 comp_func_solid_DestinationIn_rgb64,
4194 comp_func_solid_SourceOut_rgb64,
4195 comp_func_solid_DestinationOut_rgb64,
4196 comp_func_solid_SourceAtop_rgb64,
4197 comp_func_solid_DestinationAtop_rgb64,
4198 comp_func_solid_XOR_rgb64,
4199 comp_func_solid_Plus_rgb64,
4200 comp_func_solid_Multiply_rgb64,
4201 comp_func_solid_Screen_rgb64,
4202 comp_func_solid_Overlay_rgb64,
4203 comp_func_solid_Darken_rgb64,
4204 comp_func_solid_Lighten_rgb64,
4205 comp_func_solid_ColorDodge_rgb64,
4206 comp_func_solid_ColorBurn_rgb64,
4207 comp_func_solid_HardLight_rgb64,
4208 comp_func_solid_SoftLight_rgb64,
4209 comp_func_solid_Difference_rgb64,
4210 comp_func_solid_Exclusion_rgb64,
4211#else
4212 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4213 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4214 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4215#endif
4216 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4217 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
4218};
4219
4220CompositionFunctionSolidFP qt_functionForModeSolidFP_C[] = {
4221#if QT_CONFIG(raster_fp)
4222 comp_func_solid_SourceOver_rgbafp,
4223 comp_func_solid_DestinationOver_rgbafp,
4224 comp_func_solid_Clear_rgbafp,
4225 comp_func_solid_Source_rgbafp,
4226 comp_func_solid_Destination_rgbafp,
4227 comp_func_solid_SourceIn_rgbafp,
4228 comp_func_solid_DestinationIn_rgbafp,
4229 comp_func_solid_SourceOut_rgbafp,
4230 comp_func_solid_DestinationOut_rgbafp,
4231 comp_func_solid_SourceAtop_rgbafp,
4232 comp_func_solid_DestinationAtop_rgbafp,
4233 comp_func_solid_XOR_rgbafp,
4234 comp_func_solid_Plus_rgbafp,
4235 comp_func_solid_Multiply_rgbafp,
4236 comp_func_solid_Screen_rgbafp,
4237 comp_func_solid_Overlay_rgbafp,
4238 comp_func_solid_Darken_rgbafp,
4239 comp_func_solid_Lighten_rgbafp,
4240 comp_func_solid_ColorDodge_rgbafp,
4241 comp_func_solid_ColorBurn_rgbafp,
4242 comp_func_solid_HardLight_rgbafp,
4243 comp_func_solid_SoftLight_rgbafp,
4244 comp_func_solid_Difference_rgbafp,
4245 comp_func_solid_Exclusion_rgbafp,
4246#else
4247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4249#endif
4250 0, 0, 0, 0, 0, 0,
4251 0, 0, 0, 0, 0, 0, 0, 0
4252};
4253
4254CompositionFunction qt_functionForMode_C[] = {
4255 comp_func_SourceOver,
4256 comp_func_DestinationOver,
4257 comp_func_Clear,
4258 comp_func_Source,
4259 comp_func_Destination,
4260 comp_func_SourceIn,
4261 comp_func_DestinationIn,
4262 comp_func_SourceOut,
4263 comp_func_DestinationOut,
4264 comp_func_SourceAtop,
4265 comp_func_DestinationAtop,
4266 comp_func_XOR,
4267 comp_func_Plus,
4268 comp_func_Multiply,
4269 comp_func_Screen,
4270 comp_func_Overlay,
4271 comp_func_Darken,
4272 comp_func_Lighten,
4273 comp_func_ColorDodge,
4274 comp_func_ColorBurn,
4275 comp_func_HardLight,
4276 comp_func_SoftLight,
4277 comp_func_Difference,
4278 comp_func_Exclusion,
4279 rasterop_SourceOrDestination,
4280 rasterop_SourceAndDestination,
4281 rasterop_SourceXorDestination,
4282 rasterop_NotSourceAndNotDestination,
4283 rasterop_NotSourceOrNotDestination,
4284 rasterop_NotSourceXorDestination,
4285 rasterop_NotSource,
4286 rasterop_NotSourceAndDestination,
4287 rasterop_SourceAndNotDestination,
4288 rasterop_NotSourceOrDestination,
4289 rasterop_SourceOrNotDestination,
4290 rasterop_ClearDestination,
4291 rasterop_SetDestination,
4292 rasterop_NotDestination
4293};
4294
4295CompositionFunction64 qt_functionForMode64_C[] = {
4296#if QT_CONFIG(raster_64bit)
4297 comp_func_SourceOver_rgb64,
4298 comp_func_DestinationOver_rgb64,
4299 comp_func_Clear_rgb64,
4300 comp_func_Source_rgb64,
4301 comp_func_Destination_rgb64,
4302 comp_func_SourceIn_rgb64,
4303 comp_func_DestinationIn_rgb64,
4304 comp_func_SourceOut_rgb64,
4305 comp_func_DestinationOut_rgb64,
4306 comp_func_SourceAtop_rgb64,
4307 comp_func_DestinationAtop_rgb64,
4308 comp_func_XOR_rgb64,
4309 comp_func_Plus_rgb64,
4310 comp_func_Multiply_rgb64,
4311 comp_func_Screen_rgb64,
4312 comp_func_Overlay_rgb64,
4313 comp_func_Darken_rgb64,
4314 comp_func_Lighten_rgb64,
4315 comp_func_ColorDodge_rgb64,
4316 comp_func_ColorBurn_rgb64,
4317 comp_func_HardLight_rgb64,
4318 comp_func_SoftLight_rgb64,
4319 comp_func_Difference_rgb64,
4320 comp_func_Exclusion_rgb64,
4321#else
4322 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4323 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4324 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4325#endif
4326 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
4327 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
4328};
4329
4330CompositionFunctionFP qt_functionForModeFP_C[] = {
4331#if QT_CONFIG(raster_fp)
4332 comp_func_SourceOver_rgbafp,
4333 comp_func_DestinationOver_rgbafp,
4334 comp_func_Clear_rgbafp,
4335 comp_func_Source_rgbafp,
4336 comp_func_Destination_rgbafp,
4337 comp_func_SourceIn_rgbafp,
4338 comp_func_DestinationIn_rgbafp,
4339 comp_func_SourceOut_rgbafp,
4340 comp_func_DestinationOut_rgbafp,
4341 comp_func_SourceAtop_rgbafp,
4342 comp_func_DestinationAtop_rgbafp,
4343 comp_func_XOR_rgbafp,
4344 comp_func_Plus_rgbafp,
4345 comp_func_Multiply_rgbafp,
4346 comp_func_Screen_rgbafp,
4347 comp_func_Overlay_rgbafp,
4348 comp_func_Darken_rgbafp,
4349 comp_func_Lighten_rgbafp,
4350 comp_func_ColorDodge_rgbafp,
4351 comp_func_ColorBurn_rgbafp,
4352 comp_func_HardLight_rgbafp,
4353 comp_func_SoftLight_rgbafp,
4354 comp_func_Difference_rgbafp,
4355 comp_func_Exclusion_rgbafp,
4356#else
4357 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4358 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4359#endif
4360 0, 0, 0, 0, 0, 0,
4361 0, 0, 0, 0, 0, 0, 0, 0
4362};
4363
4364QT_END_NAMESPACE
4365

source code of qtbase/src/gui/painting/qcompositionfunctions.cpp