1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <qglobal.h>
41#include "qdrawhelper_p.h"
42#include "qrgba64_p.h"
43
44QT_BEGIN_NAMESPACE
45
46/* The constant alpha factor describes an alpha factor that gets applied
47 to the result of the composition operation combining it with the destination.
48
49 The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1.
50 we get the unmodified operation
51
52 result = src op dest
53 dest = result * const_alpha + dest * (1. - const_alpha)
54
55 This means that in the comments below, the first line is the const_alpha==255 case, the
56 second line the general one.
57
58 In the lines below:
59 s == src, sa == alpha(src), sia = 1 - alpha(src)
60 d == dest, da == alpha(dest), dia = 1 - alpha(dest)
61 ca = const_alpha, cia = 1 - const_alpha
62
63 The methods exist in two variants. One where we have a constant source, the other
64 where the source is an array of pixels.
65*/
66
67struct Argb32OperationsC
68{
69 typedef QRgb Type;
70 typedef quint8 Scalar;
71 typedef QRgb OptimalType;
72 typedef quint8 OptimalScalar;
73
74 static const Type clear;
75 static bool isOpaque(Type val)
76 { return qAlpha(rgb: val) == 255; }
77 static bool isTransparent(Type val)
78 { return qAlpha(rgb: val) == 0; }
79 static Scalar scalarFrom8bit(uint8_t a)
80 { return a; }
81 static void memfill(Type *ptr, Type value, qsizetype len)
82 { qt_memfill32(ptr, value, len); }
83 static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
84 { ::memcpy(dest: dest, src: src, n: len * sizeof(Type)); }
85
86 static OptimalType load(const Type *ptr)
87 { return *ptr; }
88 static OptimalType convert(const Type &val)
89 { return val; }
90 static void store(Type *ptr, OptimalType value)
91 { *ptr = value; }
92 static OptimalType add(OptimalType a, OptimalType b)
93 { return a + b; }
94 static OptimalScalar add(OptimalScalar a, OptimalScalar b)
95 { return a + b; }
96 static OptimalType plus(OptimalType a, OptimalType b)
97 { return comp_func_Plus_one_pixel(d: a, s: b); }
98 static OptimalScalar alpha(OptimalType val)
99 { return qAlpha(rgb: val); }
100 static OptimalScalar invAlpha(OptimalScalar c)
101 { return 255 - c; }
102 static OptimalScalar invAlpha(OptimalType val)
103 { return alpha(val: ~val); }
104 static OptimalScalar scalar(Scalar v)
105 { return v; }
106 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
107 { return BYTE_MUL(x: val, a); }
108 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
109 { return INTERPOLATE_PIXEL_255(x, a: a1, y, b: a2); }
110 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
111 { return BYTE_MUL(x: val, a); }
112 static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
113 { return qt_div_255(x: val * a); }
114 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
115 { return INTERPOLATE_PIXEL_255(x, a: a1, y, b: a2); }
116};
117
118const Argb32OperationsC::Type Argb32OperationsC::clear = 0;
119
120struct Rgba64OperationsBase
121{
122 typedef QRgba64 Type;
123 typedef quint16 Scalar;
124
125 static const Type clear;
126
127 static bool isOpaque(Type val)
128 { return val.isOpaque(); }
129 static bool isTransparent(Type val)
130 { return val.isTransparent(); }
131 static Scalar scalarFrom8bit(uint8_t a)
132 { return a * 257; }
133
134 static void memfill(Type *ptr, Type value, qsizetype len)
135 { qt_memfill64((quint64*)ptr, value, len); }
136 static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
137 { ::memcpy(dest: dest, src: src, n: len * sizeof(Type)); }
138};
139
140#if QT_CONFIG(raster_64bit)
141const Rgba64OperationsBase::Type Rgba64OperationsBase::clear = QRgba64::fromRgba64(c: 0);
142
143struct Rgba64OperationsC : public Rgba64OperationsBase
144{
145 typedef QRgba64 OptimalType;
146 typedef quint16 OptimalScalar;
147
148 static OptimalType load(const Type *ptr)
149 { return *ptr; }
150 static OptimalType convert(const Type &val)
151 { return val; }
152 static void store(Type *ptr, OptimalType value)
153 { *ptr = value; }
154 static OptimalType add(OptimalType a, OptimalType b)
155 { return QRgba64::fromRgba64(c: (quint64)a + (quint64)b); }
156 static OptimalScalar add(OptimalScalar a, OptimalScalar b)
157 { return a + b; }
158 static OptimalType plus(OptimalType a, OptimalType b)
159 { return addWithSaturation(a, b); }
160 static OptimalScalar alpha(OptimalType val)
161 { return val.alpha(); }
162 static OptimalScalar invAlpha(Scalar c)
163 { return 65535 - c; }
164 static OptimalScalar invAlpha(OptimalType val)
165 { return 65535 - alpha(val); }
166 static OptimalScalar scalar(Scalar v)
167 { return v; }
168 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
169 { return multiplyAlpha255(rgba64: val, alpha255: a); }
170 static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
171 { return qt_div_255(x: val * a); }
172 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
173 { return interpolate255(x, alpha1: a1, y, alpha2: a2); }
174 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
175 { return multiplyAlpha65535(rgba64: val, alpha65535: a); }
176 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
177 { return interpolate65535(x, alpha1: a1, y, alpha2: a2); }
178};
179
180#if defined(__SSE2__)
181struct Rgba64OperationsSSE2 : public Rgba64OperationsBase
182{
183 typedef __m128i OptimalType;
184 typedef __m128i OptimalScalar;
185
186 static OptimalType load(const Type *ptr)
187 {
188 return _mm_loadl_epi64(p: reinterpret_cast<const __m128i *>(ptr));
189 }
190 static OptimalType convert(const Type &value)
191 {
192#ifdef Q_PROCESSOR_X86_64
193 return _mm_cvtsi64_si128(a: value);
194#else
195 return load(&value);
196#endif
197 }
198 static void store(Type *ptr, OptimalType value)
199 {
200 _mm_storel_epi64(p: reinterpret_cast<__m128i *>(ptr), a: value);
201 }
202 static OptimalType add(OptimalType a, OptimalType b)
203 {
204 return _mm_add_epi16(a: a, b: b);
205 }
206// same as above:
207// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
208 static OptimalType plus(OptimalType a, OptimalType b)
209 {
210 return _mm_adds_epu16(a: a, b: b);
211 }
212 static OptimalScalar alpha(OptimalType c)
213 {
214 return _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3));
215 }
216 static OptimalScalar invAlpha(Scalar c)
217 {
218 return scalar(n: 65535 - c);
219 }
220 static OptimalScalar invAlpha(OptimalType c)
221 {
222 return _mm_xor_si128(a: _mm_set1_epi16(w: -1), b: alpha(c));
223 }
224 static OptimalScalar scalar(Scalar n)
225 {
226 return _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0));
227 }
228 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
229 {
230 return multiplyAlpha255(rgba64: val, alpha255: a);
231 }
232// same as above:
233// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
234 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
235 {
236 return interpolate255(x, alpha1: a1, y, alpha2: a2);
237 }
238 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
239 {
240 return multiplyAlpha65535(rgba64: val, va: a);
241 }
242 // a2 is const-ref because otherwise MSVC2015@x86 complains that it can't 16-byte align the argument.
243 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, const OptimalScalar &a2)
244 {
245 return interpolate65535(x, alpha1: a1, y, alpha2: a2);
246 }
247};
248#endif
249
250#if defined(__ARM_NEON__)
251struct Rgba64OperationsNEON : public Rgba64OperationsBase
252{
253 typedef uint16x4_t OptimalType;
254 typedef uint16x4_t OptimalScalar;
255
256 static OptimalType load(const Type *ptr)
257 {
258 return vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)));
259 }
260 static OptimalType convert(const Type &val)
261 {
262 return vreinterpret_u16_u64(vmov_n_u64(val));
263 }
264 static void store(Type *ptr, OptimalType value)
265 {
266 vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value));
267 }
268 static OptimalType add(OptimalType a, OptimalType b)
269 {
270 return vadd_u16(a, b);
271 }
272// same as above:
273// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
274 static OptimalType plus(OptimalType a, OptimalType b)
275 {
276 return vqadd_u16(a, b);
277 }
278 static OptimalScalar alpha(OptimalType c)
279 {
280 return vdup_lane_u16(c, 3);
281 }
282 static OptimalScalar invAlpha(Scalar c)
283 {
284 return scalar(65535 - c);
285 }
286 static OptimalScalar invAlpha(OptimalType c)
287 {
288 return vmvn_u16(alpha(c));
289 }
290 static OptimalScalar scalar(Scalar n)
291 {
292 return vdup_n_u16(n);
293 }
294 static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
295 {
296 return multiplyAlpha255(val, a);
297 }
298// same as above:
299// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
300 static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
301 {
302 return interpolate255(x, a1, y, a2);
303 }
304 static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
305 {
306 return multiplyAlpha65535(val, a);
307 }
308 static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
309 {
310 return interpolate65535(x, a1, y, a2);
311 }
312};
313#endif
314
315#if defined(__SSE2__)
316typedef Rgba64OperationsSSE2 Rgba64Operations;
317#elif defined(__ARM_NEON__)
318typedef Rgba64OperationsNEON Rgba64Operations;
319#else
320typedef Rgba64OperationsC Rgba64Operations;
321#endif
322#endif // QT_CONFIG(raster_64bit)
323
324typedef Argb32OperationsC Argb32Operations;
325
326/*
327 result = 0
328 d = d * cia
329*/
330template<class Ops>
331inline static void comp_func_Clear_template(typename Ops::Type *dest, int length, uint const_alpha)
332{
333 if (const_alpha == 255)
334 Ops::memfill(dest, Ops::clear, length);
335 else {
336 uint ialpha = 255 - const_alpha;
337 for (int i = 0; i < length; ++i) {
338 Ops::store(&dest[i], Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha));
339 }
340 }
341}
342
343void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
344{
345 comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
346}
347
348void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
349{
350 comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
351}
352
353#if QT_CONFIG(raster_64bit)
354void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
355{
356 comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
357}
358
359void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
360{
361 comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
362}
363#endif
364
365
366/*
367 result = s
368 dest = s * ca + d * cia
369*/
370template<class Ops>
371inline static void comp_func_solid_Source_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
372{
373 if (const_alpha == 255)
374 Ops::memfill(dest, color, length);
375 else {
376 const uint ialpha = 255 - const_alpha;
377 auto s = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
378 for (int i = 0; i < length; ++i) {
379 auto d = Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha);
380 Ops::store(&dest[i], Ops::add(s, d));
381 }
382 }
383}
384
385template<class Ops>
386inline static void comp_func_Source_template(typename Ops::Type *Q_DECL_RESTRICT dest,
387 const typename Ops::Type *Q_DECL_RESTRICT src,
388 int length, uint const_alpha)
389{
390 if (const_alpha == 255)
391 Ops::memcpy(dest, src, length);
392 else {
393 const uint ialpha = 255 - const_alpha;
394 for (int i = 0; i < length; ++i) {
395 auto s = Ops::load(src + i);
396 auto d = Ops::load(dest + i);
397 Ops::store(&dest[i], Ops::interpolate8bit(s, const_alpha, d, ialpha));
398 }
399 }
400}
401
402void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
403{
404 comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
405}
406
407void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
408{
409 comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
410}
411
412#if QT_CONFIG(raster_64bit)
413void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
414{
415 comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
416}
417
418void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
419{
420 comp_func_Source_template<Rgba64Operations>(dest, src, length, const_alpha);
421}
422#endif
423
424void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
425{
426}
427
428void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
429{
430}
431
432#if QT_CONFIG(raster_64bit)
433void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
434{
435}
436
437void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint)
438{
439}
440#endif
441
442/*
443 result = s + d * sia
444 dest = (s + d * sia) * ca + d * cia
445 = s * ca + d * (sia * ca + cia)
446 = s * ca + d * (1 - sa*ca)
447*/
448template<class Ops>
449inline static void comp_func_solid_SourceOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
450{
451 if (const_alpha == 255 && Ops::isOpaque(color))
452 Ops::memfill(dest, color, length);
453 else {
454 auto c = Ops::convert(color);
455 if (const_alpha != 255)
456 c = Ops::multiplyAlpha8bit(c, const_alpha);
457 auto cAlpha = Ops::invAlpha(c);
458 for (int i = 0; i < length; ++i) {
459 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), cAlpha);
460 Ops::store(&dest[i], Ops::add(c, d));
461 }
462 }
463}
464
465template<class Ops>
466inline static void comp_func_SourceOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
467 const typename Ops::Type *Q_DECL_RESTRICT src,
468 int length, uint const_alpha)
469{
470 if (const_alpha == 255) {
471 for (int i = 0; i < length; ++i) {
472 auto c = src[i];
473 if (Ops::isOpaque(c))
474 Ops::store(&dest[i], Ops::convert(c));
475 else if (!Ops::isTransparent(c)) {
476 auto s = Ops::convert(c);
477 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
478 Ops::store(&dest[i], Ops::add(s, d));
479 }
480 }
481 } else {
482 for (int i = 0; i < length; ++i) {
483 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
484 auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
485 Ops::store(&dest[i], Ops::add(s, d));
486 }
487 }
488}
489
490void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
491{
492 comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
493}
494
495void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
496{
497 comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
498}
499
500#if QT_CONFIG(raster_64bit)
501void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
502{
503 comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
504}
505
506void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
507{
508 comp_func_SourceOver_template<Rgba64Operations>(dest, src, length, const_alpha);
509}
510#endif
511
512/*
513 result = d + s * dia
514 dest = (d + s * dia) * ca + d * cia
515 = d + s * dia * ca
516*/
517template<class Ops>
518inline static void comp_func_solid_DestinationOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
519{
520 auto c = Ops::convert(color);
521 if (const_alpha != 255)
522 c = Ops::multiplyAlpha8bit(c, const_alpha);
523 for (int i = 0; i < length; ++i) {
524 auto d = Ops::load(&dest[i]);
525 auto s = Ops::multiplyAlpha(c, Ops::invAlpha(d));
526 Ops::store(&dest[i], Ops::add(s, d));
527 }
528}
529
530template<class Ops>
531inline static void comp_func_DestinationOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
532 const typename Ops::Type *Q_DECL_RESTRICT src,
533 int length, uint const_alpha)
534{
535 if (const_alpha == 255) {
536 for (int i = 0; i < length; ++i) {
537 auto d = Ops::load(&dest[i]);
538 auto s = Ops::multiplyAlpha(Ops::load(&src[i]), Ops::invAlpha(d));
539 Ops::store(&dest[i], Ops::add(s, d));
540 }
541 } else {
542 for (int i = 0; i < length; ++i) {
543 auto d = Ops::load(&dest[i]);
544 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
545 s = Ops::multiplyAlpha(s, Ops::invAlpha(d));
546 Ops::store(&dest[i], Ops::add(s, d));
547 }
548 }
549}
550
551void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
552{
553 comp_func_solid_DestinationOver_template<Argb32Operations>(dest, length, color, const_alpha);
554}
555
556void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
557{
558 comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
559}
560
561#if QT_CONFIG(raster_64bit)
562void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
563{
564 comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
565}
566
567void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
568{
569 comp_func_DestinationOver_template<Rgba64Operations>(dest, src, length, const_alpha);
570}
571#endif
572
573/*
574 result = s * da
575 dest = s * da * ca + d * cia
576*/
577template<class Ops>
578inline static void comp_func_solid_SourceIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
579{
580 if (const_alpha == 255) {
581 auto c = Ops::convert(color);
582 for (int i = 0; i < length; ++i) {
583 Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::alpha(Ops::load(&dest[i]))));
584 }
585 } else {
586 auto c = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
587 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
588 for (int i = 0; i < length; ++i) {
589 auto d = Ops::load(&dest[i]);
590 Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, cia));
591 }
592 }
593}
594
595template<class Ops>
596inline static void comp_func_SourceIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
597 const typename Ops::Type *Q_DECL_RESTRICT src,
598 int length, uint const_alpha)
599{
600 if (const_alpha == 255) {
601 for (int i = 0; i < length; ++i) {
602 auto s = Ops::load(&src[i]);
603 Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::alpha(Ops::load(&dest[i]))));
604 }
605 } else {
606 auto ca = Ops::scalarFrom8bit(const_alpha);
607 auto cia = Ops::invAlpha(ca);
608 auto cav = Ops::scalar(ca);
609 for (int i = 0; i < length; ++i) {
610 auto d = Ops::load(&dest[i]);
611 auto s = Ops::multiplyAlpha(Ops::load(&src[i]), cav);
612 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, cia));
613 }
614 }
615}
616
617void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
618{
619 comp_func_solid_SourceIn_template<Argb32Operations>(dest, length, color, const_alpha);
620}
621
622void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
623{
624 comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
625}
626
627#if QT_CONFIG(raster_64bit)
628void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
629{
630 comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
631}
632
633void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
634{
635 comp_func_SourceIn_template<Rgba64Operations>(dest, src, length, const_alpha);
636}
637#endif
638
639/*
640 result = d * sa
641 dest = d * sa * ca + d * cia
642 = d * (sa * ca + cia)
643*/
644template<class Ops>
645inline static void comp_func_solid_DestinationIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
646{
647 auto sa = Ops::alpha(Ops::convert(color));
648 if (const_alpha != 255) {
649 sa = Ops::multiplyAlpha8bit(sa, const_alpha);
650 sa = Ops::add(sa, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
651 }
652
653 for (int i = 0; i < length; ++i) {
654 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
655 }
656}
657
658template<class Ops>
659inline static void comp_func_DestinationIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
660 const typename Ops::Type *Q_DECL_RESTRICT src,
661 int length, uint const_alpha)
662{
663 if (const_alpha == 255) {
664 for (int i = 0; i < length; ++i) {
665 auto a = Ops::alpha(Ops::load(&src[i]));
666 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), a));
667 }
668 } else {
669 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
670 for (int i = 0; i < length; ++i) {
671 auto sa = Ops::multiplyAlpha8bit(Ops::alpha(Ops::load(&src[i])), const_alpha);
672 sa = Ops::add(sa, cia);
673 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
674 }
675 }
676}
677
678void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
679{
680 comp_func_solid_DestinationIn_template<Argb32Operations>(dest, length, color, const_alpha);
681}
682
683void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
684{
685 comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
686}
687
688#if QT_CONFIG(raster_64bit)
689void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
690{
691 comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
692}
693
694void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
695{
696 comp_func_DestinationIn_template<Rgba64Operations>(dest, src, length, const_alpha);
697}
698#endif
699
700/*
701 result = s * dia
702 dest = s * dia * ca + d * cia
703*/
704template<class Ops>
705inline static void comp_func_solid_SourceOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
706{
707 auto c = Ops::convert(color);
708 if (const_alpha == 255) {
709 for (int i = 0; i < length; ++i)
710 Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::invAlpha(Ops::load(&dest[i]))));
711 } else {
712 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
713 c = Ops::multiplyAlpha8bit(c, const_alpha);
714 for (int i = 0; i < length; ++i) {
715 auto d = Ops::load(&dest[i]);
716 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, cia));
717 }
718 }
719}
720
721template<class Ops>
722inline static void comp_func_SourceOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
723 const typename Ops::Type *Q_DECL_RESTRICT src,
724 int length, uint const_alpha)
725{
726 if (const_alpha == 255) {
727 for (int i = 0; i < length; ++i) {
728 auto s = Ops::load(&src[i]);
729 auto d = Ops::load(&dest[i]);
730 Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::invAlpha(d)));
731 }
732 } else {
733 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
734 for (int i = 0; i < length; ++i) {
735 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
736 auto d = Ops::load(&dest[i]);
737 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, cia));
738 }
739 }
740}
741
742void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
743{
744 comp_func_solid_SourceOut_template<Argb32Operations>(dest, length, color, const_alpha);
745}
746
747void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
748{
749 comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
750}
751
752#if QT_CONFIG(raster_64bit)
753void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
754{
755 comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
756}
757
758void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
759{
760 comp_func_SourceOut_template<Rgba64Operations>(dest, src, length, const_alpha);
761}
762#endif
763
764/*
765 result = d * sia
766 dest = d * sia * ca + d * cia
767 = d * (sia * ca + cia)
768*/
769template<class Ops>
770inline static void comp_func_solid_DestinationOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
771{
772 auto sai = Ops::invAlpha(Ops::convert(color));
773 if (const_alpha != 255) {
774 sai = Ops::multiplyAlpha8bit(sai, const_alpha);
775 sai = Ops::add(sai, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
776 }
777
778 for (int i = 0; i < length; ++i) {
779 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sai));
780 }
781}
782
783template<class Ops>
784inline static void comp_func_DestinationOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
785 const typename Ops::Type *Q_DECL_RESTRICT src,
786 int length, uint const_alpha)
787{
788 if (const_alpha == 255) {
789 for (int i = 0; i < length; ++i) {
790 auto sia = Ops::invAlpha(Ops::load(&src[i]));
791 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
792 }
793 } else {
794 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
795 for (int i = 0; i < length; ++i) {
796 auto sia = Ops::multiplyAlpha8bit(Ops::invAlpha(Ops::load(&src[i])), const_alpha);
797 sia = Ops::add(sia, cia);
798 Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
799 }
800 }
801}
802
803void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
804{
805 comp_func_solid_DestinationOut_template<Argb32Operations>(dest, length, color, const_alpha);
806}
807
808void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
809{
810 comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
811}
812
813#if QT_CONFIG(raster_64bit)
814void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
815{
816 comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
817}
818
819void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
820{
821 comp_func_DestinationOut_template<Rgba64Operations>(dest, src, length, const_alpha);
822}
823#endif
824
825/*
826 result = s*da + d*sia
827 dest = s*da*ca + d*sia*ca + d *cia
828 = s*ca * da + d * (sia*ca + cia)
829 = s*ca * da + d * (1 - sa*ca)
830*/
831template<class Ops>
832inline static void comp_func_solid_SourceAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
833{
834 auto c = Ops::convert(color);
835 if (const_alpha != 255)
836 c = Ops::multiplyAlpha8bit(c, const_alpha);
837 auto sia = Ops::invAlpha(c);
838 for (int i = 0; i < length; ++i) {
839 auto d = Ops::load(&dest[i]);
840 Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, sia));
841 }
842}
843
844template<class Ops>
845inline static void comp_func_SourceAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
846 const typename Ops::Type *Q_DECL_RESTRICT src,
847 int length, uint const_alpha)
848{
849 if (const_alpha == 255) {
850 for (int i = 0; i < length; ++i) {
851 auto s = Ops::load(&src[i]);
852 auto d = Ops::load(&dest[i]);
853 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
854 }
855 } else {
856 for (int i = 0; i < length; ++i) {
857 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
858 auto d = Ops::load(&dest[i]);
859 Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
860 }
861 }
862}
863
864void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
865{
866 comp_func_solid_SourceAtop_template<Argb32Operations>(dest, length, color, const_alpha);
867}
868
869void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
870{
871 comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
872}
873
874#if QT_CONFIG(raster_64bit)
875void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
876{
877 comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
878}
879
880void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
881{
882 comp_func_SourceAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
883}
884#endif
885
886/*
887 result = d*sa + s*dia
888 dest = d*sa*ca + s*dia*ca + d *cia
889 = s*ca * dia + d * (sa*ca + cia)
890*/
891template<class Ops>
892inline static void comp_func_solid_DestinationAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
893{
894 auto c = Ops::convert(color);
895 auto sa = Ops::alpha(c);
896 if (const_alpha != 255) {
897 c = Ops::multiplyAlpha8bit(c, const_alpha);
898 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
899 sa = Ops::add(Ops::alpha(c), cia);
900 }
901
902 for (int i = 0; i < length; ++i) {
903 auto d = Ops::load(&dest[i]);
904 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sa));
905 }
906}
907
908template<class Ops>
909inline static void comp_func_DestinationAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
910 const typename Ops::Type *Q_DECL_RESTRICT src,
911 int length, uint const_alpha)
912{
913 if (const_alpha == 255) {
914 for (int i = 0; i < length; ++i) {
915 auto s = Ops::load(&src[i]);
916 auto d = Ops::load(&dest[i]);
917 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::alpha(s)));
918 }
919 } else {
920 auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
921 for (int i = 0; i < length; ++i) {
922 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
923 auto d = Ops::load(&dest[i]);
924 auto sa = Ops::add(Ops::alpha(s), cia);
925 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, sa));
926 }
927 }
928}
929
930void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
931{
932 comp_func_solid_DestinationAtop_template<Argb32Operations>(dest, length, color, const_alpha);
933}
934
935void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
936{
937 comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
938}
939
940#if QT_CONFIG(raster_64bit)
941void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
942{
943 comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
944}
945
946void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
947{
948 comp_func_DestinationAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
949}
950#endif
951
952/*
953 result = d*sia + s*dia
954 dest = d*sia*ca + s*dia*ca + d *cia
955 = s*ca * dia + d * (sia*ca + cia)
956 = s*ca * dia + d * (1 - sa*ca)
957*/
958template<class Ops>
959inline static void comp_func_solid_XOR_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
960{
961 auto c = Ops::convert(color);
962 if (const_alpha != 255)
963 c = Ops::multiplyAlpha8bit(c, const_alpha);
964
965 auto sia = Ops::invAlpha(c);
966 for (int i = 0; i < length; ++i) {
967 auto d = Ops::load(&dest[i]);
968 Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sia));
969 }
970}
971
972template<class Ops>
973inline static void comp_func_XOR_template(typename Ops::Type *Q_DECL_RESTRICT dest,
974 const typename Ops::Type *Q_DECL_RESTRICT src,
975 int length, uint const_alpha)
976{
977 if (const_alpha == 255) {
978 for (int i = 0; i < length; ++i) {
979 auto d = Ops::load(&dest[i]);
980 auto s = Ops::load(&src[i]);
981 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
982 }
983 } else {
984 for (int i = 0; i < length; ++i) {
985 auto d = Ops::load(&dest[i]);
986 auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
987 Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
988 }
989 }
990}
991
992void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
993{
994 comp_func_solid_XOR_template<Argb32Operations>(dest, length, color, const_alpha);
995}
996
997void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
998{
999 comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
1000}
1001
1002#if QT_CONFIG(raster_64bit)
1003void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1004{
1005 comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
1006}
1007
1008void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1009{
1010 comp_func_XOR_template<Rgba64Operations>(dest, src, length, const_alpha);
1011}
1012#endif
1013
1014struct QFullCoverage {
1015 inline void store(uint *dest, const uint src) const
1016 {
1017 *dest = src;
1018 }
1019 inline void store(QRgba64 *dest, const QRgba64 src) const
1020 {
1021 *dest = src;
1022 }
1023};
1024
1025struct QPartialCoverage {
1026 inline QPartialCoverage(uint const_alpha)
1027 : ca(const_alpha)
1028 , ica(255 - const_alpha)
1029 {
1030 }
1031
1032 inline void store(uint *dest, const uint src) const
1033 {
1034 *dest = INTERPOLATE_PIXEL_255(x: src, a: ca, y: *dest, b: ica);
1035 }
1036 inline void store(QRgba64 *dest, const QRgba64 src) const
1037 {
1038 *dest = interpolate255(x: src, alpha1: ca, y: *dest, alpha2: ica);
1039 }
1040
1041private:
1042 const uint ca;
1043 const uint ica;
1044};
1045
1046static inline int mix_alpha(int da, int sa)
1047{
1048 return 255 - qt_div_255(x: (255 - sa) * (255 - da));
1049}
1050
1051static inline uint mix_alpha_rgb64(uint da, uint sa)
1052{
1053 return 65535U - qt_div_65535(x: (65535U - sa) * (65535U - da));
1054}
1055
1056/*
1057 Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
1058 = Sca + Dca
1059*/
1060template<class Ops>
1061inline static void comp_func_solid_Plus_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
1062{
1063 auto c = Ops::convert(color);
1064 if (const_alpha == 255) {
1065 for (int i = 0; i < length; ++i) {
1066 auto d = Ops::load(&dest[i]);
1067 d = Ops::plus(d, c);
1068 Ops::store(&dest[i], d);
1069 }
1070 } else {
1071 uint ia = 255 - const_alpha;
1072 for (int i = 0; i < length; ++i) {
1073 auto d = Ops::load(&dest[i]);
1074 d = Ops::interpolate8bit(Ops::plus(d, c), const_alpha, d, ia);
1075 Ops::store(&dest[i], d);
1076 }
1077 }
1078}
1079
1080template<class Ops>
1081inline static void comp_func_Plus_template(typename Ops::Type *Q_DECL_RESTRICT dest,
1082 const typename Ops::Type *Q_DECL_RESTRICT src,
1083 int length, uint const_alpha)
1084{
1085 if (const_alpha == 255) {
1086 for (int i = 0; i < length; ++i) {
1087 auto d = Ops::load(&dest[i]);
1088 auto s = Ops::load(&src[i]);
1089 d = Ops::plus(d, s);
1090 Ops::store(&dest[i], d);
1091 }
1092 } else {
1093 uint ia = 255 - const_alpha;
1094 for (int i = 0; i < length; ++i) {
1095 auto d = Ops::load(&dest[i]);
1096 auto s = Ops::load(&src[i]);
1097 d = Ops::interpolate8bit(Ops::plus(d, s), const_alpha, d, ia);
1098 Ops::store(&dest[i], d);
1099 }
1100 }
1101}
1102
1103void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
1104{
1105 comp_func_solid_Plus_template<Argb32Operations>(dest, length, color, const_alpha);
1106}
1107
1108void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1109{
1110 comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
1111}
1112
1113#if QT_CONFIG(raster_64bit)
1114void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1115{
1116 comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
1117}
1118
1119void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1120{
1121 comp_func_Plus_template<Rgba64Operations>(dest, src, length, const_alpha);
1122}
1123#endif
1124
1125/*
1126 Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
1127*/
1128static inline int multiply_op(int dst, int src, int da, int sa)
1129{
1130 return qt_div_255(x: src * dst + src * (255 - da) + dst * (255 - sa));
1131}
1132
1133template <typename T>
1134static inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
1135{
1136 int sa = qAlpha(rgb: color);
1137 int sr = qRed(rgb: color);
1138 int sg = qGreen(rgb: color);
1139 int sb = qBlue(rgb: color);
1140
1141 for (int i = 0; i < length; ++i) {
1142 uint d = dest[i];
1143 int da = qAlpha(rgb: d);
1144
1145#define OP(a, b) multiply_op(a, b, da, sa)
1146 int r = OP( qRed(d), sr);
1147 int b = OP( qBlue(d), sb);
1148 int g = OP(qGreen(d), sg);
1149 int a = mix_alpha(da, sa);
1150#undef OP
1151
1152 coverage.store(&dest[i], qRgba(r, g, b, a));
1153 }
1154}
1155
1156void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
1157{
1158 if (const_alpha == 255)
1159 comp_func_solid_Multiply_impl(dest, length, color, coverage: QFullCoverage());
1160 else
1161 comp_func_solid_Multiply_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1162}
1163
1164#if QT_CONFIG(raster_64bit)
1165static inline uint multiply_op_rgb64(uint dst, uint src, uint da, uint sa)
1166{
1167 return qt_div_65535(x: src * dst + src * (65535 - da) + dst * (65535 - sa));
1168}
1169
1170template <typename T>
1171static inline void comp_func_solid_Multiply_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1172{
1173 uint sa = color.alpha();
1174 uint sr = color.red();
1175 uint sg = color.green();
1176 uint sb = color.blue();
1177
1178 for (int i = 0; i < length; ++i) {
1179 QRgba64 d = dest[i];
1180 uint da = d.alpha();
1181
1182#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
1183 uint r = OP( d.red(), sr);
1184 uint b = OP( d.blue(), sb);
1185 uint g = OP(d.green(), sg);
1186 uint a = mix_alpha_rgb64(da, sa);
1187#undef OP
1188
1189 coverage.store(&dest[i], qRgba64(r, g, b, a));
1190 }
1191}
1192
1193void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1194{
1195 if (const_alpha == 255)
1196 comp_func_solid_Multiply_impl(dest, length, color, coverage: QFullCoverage());
1197 else
1198 comp_func_solid_Multiply_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1199}
1200#endif
1201
1202template <typename T>
1203static inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1204{
1205 for (int i = 0; i < length; ++i) {
1206 uint d = dest[i];
1207 uint s = src[i];
1208
1209 int da = qAlpha(rgb: d);
1210 int sa = qAlpha(rgb: s);
1211
1212#define OP(a, b) multiply_op(a, b, da, sa)
1213 int r = OP( qRed(d), qRed(s));
1214 int b = OP( qBlue(d), qBlue(s));
1215 int g = OP(qGreen(d), qGreen(s));
1216 int a = mix_alpha(da, sa);
1217#undef OP
1218
1219 coverage.store(&dest[i], qRgba(r, g, b, a));
1220 }
1221}
1222
1223void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1224{
1225 if (const_alpha == 255)
1226 comp_func_Multiply_impl(dest, src, length, coverage: QFullCoverage());
1227 else
1228 comp_func_Multiply_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1229}
1230
1231#if QT_CONFIG(raster_64bit)
1232template <typename T>
1233static inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1234{
1235 for (int i = 0; i < length; ++i) {
1236 QRgba64 d = dest[i];
1237 QRgba64 s = src[i];
1238
1239 uint da = d.alpha();
1240 uint sa = s.alpha();
1241
1242#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
1243 uint r = OP( d.red(), s.red());
1244 uint b = OP( d.blue(), s.blue());
1245 uint g = OP(d.green(), s.green());
1246 uint a = mix_alpha_rgb64(da, sa);
1247#undef OP
1248
1249 coverage.store(&dest[i], qRgba64(r, g, b, a));
1250 }
1251}
1252
1253void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1254{
1255 if (const_alpha == 255)
1256 comp_func_Multiply_impl(dest, src, length, coverage: QFullCoverage());
1257 else
1258 comp_func_Multiply_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1259}
1260#endif
1261
1262/*
1263 Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
1264 = Sca + Dca - Sca.Dca
1265*/
1266template <typename T>
1267static inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
1268{
1269 int sa = qAlpha(rgb: color);
1270 int sr = qRed(rgb: color);
1271 int sg = qGreen(rgb: color);
1272 int sb = qBlue(rgb: color);
1273
1274 for (int i = 0; i < length; ++i) {
1275 uint d = dest[i];
1276 int da = qAlpha(rgb: d);
1277
1278#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
1279 int r = OP( qRed(d), sr);
1280 int b = OP( qBlue(d), sb);
1281 int g = OP(qGreen(d), sg);
1282 int a = mix_alpha(da, sa);
1283#undef OP
1284
1285 coverage.store(&dest[i], qRgba(r, g, b, a));
1286 }
1287}
1288
1289void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
1290{
1291 if (const_alpha == 255)
1292 comp_func_solid_Screen_impl(dest, length, color, coverage: QFullCoverage());
1293 else
1294 comp_func_solid_Screen_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1295}
1296
1297#if QT_CONFIG(raster_64bit)
1298template <typename T>
1299static inline void comp_func_solid_Screen_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1300{
1301 uint sa = color.alpha();
1302 uint sr = color.red();
1303 uint sg = color.green();
1304 uint sb = color.blue();
1305
1306 for (int i = 0; i < length; ++i) {
1307 QRgba64 d = dest[i];
1308 uint da = d.alpha();
1309
1310#define OP(a, b) 65535 - qt_div_65535((65535-a) * (65535-b))
1311 uint r = OP( d.red(), sr);
1312 uint b = OP( d.blue(), sb);
1313 uint g = OP(d.green(), sg);
1314 uint a = mix_alpha_rgb64(da, sa);
1315#undef OP
1316
1317 coverage.store(&dest[i], qRgba64(r, g, b, a));
1318 }
1319}
1320
1321void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1322{
1323 if (const_alpha == 255)
1324 comp_func_solid_Screen_impl(dest, length, color, coverage: QFullCoverage());
1325 else
1326 comp_func_solid_Screen_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1327}
1328#endif
1329
1330template <typename T>
1331static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1332{
1333 for (int i = 0; i < length; ++i) {
1334 uint d = dest[i];
1335 uint s = src[i];
1336
1337 int da = qAlpha(rgb: d);
1338 int sa = qAlpha(rgb: s);
1339
1340#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
1341 int r = OP( qRed(d), qRed(s));
1342 int b = OP( qBlue(d), qBlue(s));
1343 int g = OP(qGreen(d), qGreen(s));
1344 int a = mix_alpha(da, sa);
1345#undef OP
1346
1347 coverage.store(&dest[i], qRgba(r, g, b, a));
1348 }
1349}
1350
1351void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
1352{
1353 if (const_alpha == 255)
1354 comp_func_Screen_impl(dest, src, length, coverage: QFullCoverage());
1355 else
1356 comp_func_Screen_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1357}
1358
1359#if QT_CONFIG(raster_64bit)
1360template <typename T>
1361static inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1362{
1363 for (int i = 0; i < length; ++i) {
1364 QRgba64 d = dest[i];
1365 QRgba64 s = src[i];
1366
1367 uint da = d.alpha();
1368 uint sa = s.alpha();
1369
1370#define OP(a, b) 65535U - qt_div_65535((65535U-a) * (65535U-b))
1371 uint r = OP( d.red(), s.red());
1372 uint b = OP( d.blue(), s.blue());
1373 uint g = OP(d.green(), s.green());
1374 uint a = mix_alpha_rgb64(da, sa);
1375#undef OP
1376
1377 coverage.store(&dest[i], qRgba64(r, g, b, a));
1378 }
1379}
1380
1381void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int length, uint const_alpha)
1382{
1383 if (const_alpha == 255)
1384 comp_func_Screen_impl(dest, src, length, coverage: QFullCoverage());
1385 else
1386 comp_func_Screen_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1387}
1388#endif
1389
1390/*
1391 if 2.Dca < Da
1392 Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
1393 otherwise
1394 Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
1395*/
1396static inline int overlay_op(int dst, int src, int da, int sa)
1397{
1398 const int temp = src * (255 - da) + dst * (255 - sa);
1399 if (2 * dst < da)
1400 return qt_div_255(x: 2 * src * dst + temp);
1401 else
1402 return qt_div_255(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
1403}
1404
1405template <typename T>
1406static inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
1407{
1408 int sa = qAlpha(rgb: color);
1409 int sr = qRed(rgb: color);
1410 int sg = qGreen(rgb: color);
1411 int sb = qBlue(rgb: color);
1412
1413 for (int i = 0; i < length; ++i) {
1414 uint d = dest[i];
1415 int da = qAlpha(rgb: d);
1416
1417#define OP(a, b) overlay_op(a, b, da, sa)
1418 int r = OP( qRed(d), sr);
1419 int b = OP( qBlue(d), sb);
1420 int g = OP(qGreen(d), sg);
1421 int a = mix_alpha(da, sa);
1422#undef OP
1423
1424 coverage.store(&dest[i], qRgba(r, g, b, a));
1425 }
1426}
1427
1428void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
1429{
1430 if (const_alpha == 255)
1431 comp_func_solid_Overlay_impl(dest, length, color, coverage: QFullCoverage());
1432 else
1433 comp_func_solid_Overlay_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1434}
1435
1436#if QT_CONFIG(raster_64bit)
1437static inline uint overlay_op_rgb64(uint dst, uint src, uint da, uint sa)
1438{
1439 const uint temp = src * (65535 - da) + dst * (65535 - sa);
1440 if (2 * dst < da)
1441 return qt_div_65535(x: 2 * src * dst + temp);
1442 else
1443 return qt_div_65535(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
1444}
1445
1446template <typename T>
1447static inline void comp_func_solid_Overlay_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1448{
1449 uint sa = color.alpha();
1450 uint sr = color.red();
1451 uint sg = color.green();
1452 uint sb = color.blue();
1453
1454 for (int i = 0; i < length; ++i) {
1455 QRgba64 d = dest[i];
1456 uint da = d.alpha();
1457
1458#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
1459 uint r = OP( d.red(), sr);
1460 uint b = OP( d.blue(), sb);
1461 uint g = OP(d.green(), sg);
1462 uint a = mix_alpha_rgb64(da, sa);
1463#undef OP
1464
1465 coverage.store(&dest[i], qRgba64(r, g, b, a));
1466 }
1467}
1468
1469void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1470{
1471 if (const_alpha == 255)
1472 comp_func_solid_Overlay_impl(dest, length, color, coverage: QFullCoverage());
1473 else
1474 comp_func_solid_Overlay_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1475}
1476#endif
1477
1478template <typename T>
1479static inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1480{
1481 for (int i = 0; i < length; ++i) {
1482 uint d = dest[i];
1483 uint s = src[i];
1484
1485 int da = qAlpha(rgb: d);
1486 int sa = qAlpha(rgb: s);
1487
1488#define OP(a, b) overlay_op(a, b, da, sa)
1489 int r = OP( qRed(d), qRed(s));
1490 int b = OP( qBlue(d), qBlue(s));
1491 int g = OP(qGreen(d), qGreen(s));
1492 int a = mix_alpha(da, sa);
1493#undef OP
1494
1495 coverage.store(&dest[i], qRgba(r, g, b, a));
1496 }
1497}
1498
1499void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1500{
1501 if (const_alpha == 255)
1502 comp_func_Overlay_impl(dest, src, length, coverage: QFullCoverage());
1503 else
1504 comp_func_Overlay_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1505}
1506
1507#if QT_CONFIG(raster_64bit)
1508template <typename T>
1509static inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1510{
1511 for (int i = 0; i < length; ++i) {
1512 QRgba64 d = dest[i];
1513 QRgba64 s = src[i];
1514
1515 uint da = d.alpha();
1516 uint sa = s.alpha();
1517
1518#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
1519 uint r = OP( d.red(), s.red());
1520 uint b = OP( d.blue(), s.blue());
1521 uint g = OP(d.green(), s.green());
1522 uint a = mix_alpha_rgb64(da, sa);
1523#undef OP
1524
1525 coverage.store(&dest[i], qRgba64(r, g, b, a));
1526 }
1527}
1528
1529void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1530{
1531 if (const_alpha == 255)
1532 comp_func_Overlay_impl(dest, src, length, coverage: QFullCoverage());
1533 else
1534 comp_func_Overlay_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1535}
1536#endif
1537
1538/*
1539 Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
1540 Da' = Sa + Da - Sa.Da
1541*/
1542static inline int darken_op(int dst, int src, int da, int sa)
1543{
1544 return qt_div_255(x: qMin(a: src * da, b: dst * sa) + src * (255 - da) + dst * (255 - sa));
1545}
1546
1547template <typename T>
1548static inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
1549{
1550 int sa = qAlpha(rgb: color);
1551 int sr = qRed(rgb: color);
1552 int sg = qGreen(rgb: color);
1553 int sb = qBlue(rgb: color);
1554
1555 for (int i = 0; i < length; ++i) {
1556 uint d = dest[i];
1557 int da = qAlpha(rgb: d);
1558
1559#define OP(a, b) darken_op(a, b, da, sa)
1560 int r = OP( qRed(d), sr);
1561 int b = OP( qBlue(d), sb);
1562 int g = OP(qGreen(d), sg);
1563 int a = mix_alpha(da, sa);
1564#undef OP
1565
1566 coverage.store(&dest[i], qRgba(r, g, b, a));
1567 }
1568}
1569
1570void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
1571{
1572 if (const_alpha == 255)
1573 comp_func_solid_Darken_impl(dest, length, color, coverage: QFullCoverage());
1574 else
1575 comp_func_solid_Darken_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1576}
1577
1578#if QT_CONFIG(raster_64bit)
1579static inline uint darken_op_rgb64(uint dst, uint src, uint da, uint sa)
1580{
1581 return qt_div_65535(x: qMin(a: src * da, b: dst * sa) + src * (65535 - da) + dst * (65535 - sa));
1582}
1583
1584template <typename T>
1585static inline void comp_func_solid_Darken_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1586{
1587 uint sa = color.alpha();
1588 uint sr = color.red();
1589 uint sg = color.green();
1590 uint sb = color.blue();
1591
1592 for (int i = 0; i < length; ++i) {
1593 QRgba64 d = dest[i];
1594 uint da = d.alpha();
1595
1596#define OP(a, b) darken_op_rgb64(a, b, da, sa)
1597 uint r = OP( d.red(), sr);
1598 uint b = OP( d.blue(), sb);
1599 uint g = OP(d.green(), sg);
1600 uint a = mix_alpha_rgb64(da, sa);
1601#undef OP
1602
1603 coverage.store(&dest[i], qRgba64(r, g, b, a));
1604 }
1605}
1606
1607void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1608{
1609 if (const_alpha == 255)
1610 comp_func_solid_Darken_impl(dest, length, color, coverage: QFullCoverage());
1611 else
1612 comp_func_solid_Darken_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1613}
1614#endif
1615
1616template <typename T>
1617static inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1618{
1619 for (int i = 0; i < length; ++i) {
1620 uint d = dest[i];
1621 uint s = src[i];
1622
1623 int da = qAlpha(rgb: d);
1624 int sa = qAlpha(rgb: s);
1625
1626#define OP(a, b) darken_op(a, b, da, sa)
1627 int r = OP( qRed(d), qRed(s));
1628 int b = OP( qBlue(d), qBlue(s));
1629 int g = OP(qGreen(d), qGreen(s));
1630 int a = mix_alpha(da, sa);
1631#undef OP
1632
1633 coverage.store(&dest[i], qRgba(r, g, b, a));
1634 }
1635}
1636
1637void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1638{
1639 if (const_alpha == 255)
1640 comp_func_Darken_impl(dest, src, length, coverage: QFullCoverage());
1641 else
1642 comp_func_Darken_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1643}
1644
1645#if QT_CONFIG(raster_64bit)
1646template <typename T>
1647static inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1648{
1649 for (int i = 0; i < length; ++i) {
1650 QRgba64 d = dest[i];
1651 QRgba64 s = src[i];
1652
1653 uint da = d.alpha();
1654 uint sa = s.alpha();
1655
1656#define OP(a, b) darken_op_rgb64(a, b, da, sa)
1657 uint r = OP( d.red(), s.red());
1658 uint b = OP( d.blue(), s.blue());
1659 uint g = OP(d.green(), s.green());
1660 uint a = mix_alpha_rgb64(da, sa);
1661#undef OP
1662
1663 coverage.store(&dest[i], qRgba64(r, g, b, a));
1664 }
1665}
1666
1667void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1668{
1669 if (const_alpha == 255)
1670 comp_func_Darken_impl(dest, src, length, coverage: QFullCoverage());
1671 else
1672 comp_func_Darken_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1673}
1674#endif
1675
1676/*
1677 Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
1678 Da' = Sa + Da - Sa.Da
1679*/
1680static inline int lighten_op(int dst, int src, int da, int sa)
1681{
1682 return qt_div_255(x: qMax(a: src * da, b: dst * sa) + src * (255 - da) + dst * (255 - sa));
1683}
1684
1685template <typename T>
1686static inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
1687{
1688 int sa = qAlpha(rgb: color);
1689 int sr = qRed(rgb: color);
1690 int sg = qGreen(rgb: color);
1691 int sb = qBlue(rgb: color);
1692
1693 for (int i = 0; i < length; ++i) {
1694 uint d = dest[i];
1695 int da = qAlpha(rgb: d);
1696
1697#define OP(a, b) lighten_op(a, b, da, sa)
1698 int r = OP( qRed(d), sr);
1699 int b = OP( qBlue(d), sb);
1700 int g = OP(qGreen(d), sg);
1701 int a = mix_alpha(da, sa);
1702#undef OP
1703
1704 coverage.store(&dest[i], qRgba(r, g, b, a));
1705 }
1706}
1707
1708void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
1709{
1710 if (const_alpha == 255)
1711 comp_func_solid_Lighten_impl(dest, length, color, coverage: QFullCoverage());
1712 else
1713 comp_func_solid_Lighten_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1714}
1715
1716
1717#if QT_CONFIG(raster_64bit)
1718static inline uint lighten_op_rgb64(uint dst, uint src, uint da, uint sa)
1719{
1720 return qt_div_65535(x: qMax(a: src * da, b: dst * sa) + src * (65535 - da) + dst * (65535 - sa));
1721}
1722
1723template <typename T>
1724static inline void comp_func_solid_Lighten_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1725{
1726 uint sa = color.alpha();
1727 uint sr = color.red();
1728 uint sg = color.green();
1729 uint sb = color.blue();
1730
1731 for (int i = 0; i < length; ++i) {
1732 QRgba64 d = dest[i];
1733 uint da = d.alpha();
1734
1735#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
1736 uint r = OP( d.red(), sr);
1737 uint b = OP( d.blue(), sb);
1738 uint g = OP(d.green(), sg);
1739 uint a = mix_alpha_rgb64(da, sa);
1740#undef OP
1741
1742 coverage.store(&dest[i], qRgba64(r, g, b, a));
1743 }
1744}
1745
1746void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1747{
1748 if (const_alpha == 255)
1749 comp_func_solid_Lighten_impl(dest, length, color, coverage: QFullCoverage());
1750 else
1751 comp_func_solid_Lighten_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1752}
1753#endif
1754
1755template <typename T>
1756static inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1757{
1758 for (int i = 0; i < length; ++i) {
1759 uint d = dest[i];
1760 uint s = src[i];
1761
1762 int da = qAlpha(rgb: d);
1763 int sa = qAlpha(rgb: s);
1764
1765#define OP(a, b) lighten_op(a, b, da, sa)
1766 int r = OP( qRed(d), qRed(s));
1767 int b = OP( qBlue(d), qBlue(s));
1768 int g = OP(qGreen(d), qGreen(s));
1769 int a = mix_alpha(da, sa);
1770#undef OP
1771
1772 coverage.store(&dest[i], qRgba(r, g, b, a));
1773 }
1774}
1775
1776void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1777{
1778 if (const_alpha == 255)
1779 comp_func_Lighten_impl(dest, src, length, coverage: QFullCoverage());
1780 else
1781 comp_func_Lighten_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1782}
1783
1784#if QT_CONFIG(raster_64bit)
1785template <typename T>
1786static inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1787{
1788 for (int i = 0; i < length; ++i) {
1789 QRgba64 d = dest[i];
1790 QRgba64 s = src[i];
1791
1792 uint da = d.alpha();
1793 uint sa = s.alpha();
1794
1795#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
1796 uint r = OP( d.red(), s.red());
1797 uint b = OP( d.blue(), s.blue());
1798 uint g = OP(d.green(), s.green());
1799 uint a = mix_alpha_rgb64(da, sa);
1800#undef OP
1801
1802 coverage.store(&dest[i], qRgba64(r, g, b, a));
1803 }
1804}
1805
1806void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1807{
1808 if (const_alpha == 255)
1809 comp_func_Lighten_impl(dest, src, length, coverage: QFullCoverage());
1810 else
1811 comp_func_Lighten_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1812}
1813#endif
1814
1815/*
1816 if Sca.Da + Dca.Sa > Sa.Da
1817 Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
1818 else if Sca == Sa
1819 Dca' = Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
1820 otherwise
1821 Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
1822*/
1823static inline int color_dodge_op(int dst, int src, int da, int sa)
1824{
1825 const int sa_da = sa * da;
1826 const int dst_sa = dst * sa;
1827 const int src_da = src * da;
1828
1829 const int temp = src * (255 - da) + dst * (255 - sa);
1830 if (src_da + dst_sa > sa_da)
1831 return qt_div_255(x: sa_da + temp);
1832 else if (src == sa || sa == 0)
1833 return qt_div_255(x: temp);
1834 else
1835 return qt_div_255(x: 255 * dst_sa / (255 - 255 * src / sa) + temp);
1836}
1837
1838template <typename T>
1839static inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
1840{
1841 int sa = qAlpha(rgb: color);
1842 int sr = qRed(rgb: color);
1843 int sg = qGreen(rgb: color);
1844 int sb = qBlue(rgb: color);
1845
1846 for (int i = 0; i < length; ++i) {
1847 uint d = dest[i];
1848 int da = qAlpha(rgb: d);
1849
1850#define OP(a,b) color_dodge_op(a, b, da, sa)
1851 int r = OP( qRed(d), sr);
1852 int b = OP( qBlue(d), sb);
1853 int g = OP(qGreen(d), sg);
1854 int a = mix_alpha(da, sa);
1855#undef OP
1856
1857 coverage.store(&dest[i], qRgba(r, g, b, a));
1858 }
1859}
1860
1861void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
1862{
1863 if (const_alpha == 255)
1864 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QFullCoverage());
1865 else
1866 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1867}
1868
1869#if QT_CONFIG(raster_64bit)
1870static inline uint color_dodge_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
1871{
1872 const qint64 sa_da = sa * da;
1873 const qint64 dst_sa = dst * sa;
1874 const qint64 src_da = src * da;
1875
1876 const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
1877 if (src_da + dst_sa > sa_da)
1878 return qt_div_65535(x: sa_da + temp);
1879 else if (src == sa || sa == 0)
1880 return qt_div_65535(x: temp);
1881 else
1882 return qt_div_65535(x: 65535 * dst_sa / (65535 - 65535 * src / sa) + temp);
1883}
1884
1885template <typename T>
1886static inline void comp_func_solid_ColorDodge_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
1887{
1888 uint sa = color.alpha();
1889 uint sr = color.red();
1890 uint sg = color.green();
1891 uint sb = color.blue();
1892
1893 for (int i = 0; i < length; ++i) {
1894 QRgba64 d = dest[i];
1895 uint da = d.alpha();
1896
1897#define OP(a,b) color_dodge_op_rgb64(a, b, da, sa)
1898 uint r = OP( d.red(), sr);
1899 uint b = OP( d.blue(), sb);
1900 uint g = OP(d.green(), sg);
1901 uint a = mix_alpha_rgb64(da, sa);
1902#undef OP
1903
1904 coverage.store(&dest[i], qRgba64(r, g, b, a));
1905 }
1906}
1907
1908void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
1909{
1910 if (const_alpha == 255)
1911 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QFullCoverage());
1912 else
1913 comp_func_solid_ColorDodge_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
1914}
1915#endif
1916
1917template <typename T>
1918static inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
1919{
1920 for (int i = 0; i < length; ++i) {
1921 uint d = dest[i];
1922 uint s = src[i];
1923
1924 int da = qAlpha(rgb: d);
1925 int sa = qAlpha(rgb: s);
1926
1927#define OP(a, b) color_dodge_op(a, b, da, sa)
1928 int r = OP( qRed(d), qRed(s));
1929 int b = OP( qBlue(d), qBlue(s));
1930 int g = OP(qGreen(d), qGreen(s));
1931 int a = mix_alpha(da, sa);
1932#undef OP
1933
1934 coverage.store(&dest[i], qRgba(r, g, b, a));
1935 }
1936}
1937
1938void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
1939{
1940 if (const_alpha == 255)
1941 comp_func_ColorDodge_impl(dest, src, length, coverage: QFullCoverage());
1942 else
1943 comp_func_ColorDodge_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1944}
1945
1946#if QT_CONFIG(raster_64bit)
1947template <typename T>
1948static inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
1949{
1950 for (int i = 0; i < length; ++i) {
1951 QRgba64 d = dest[i];
1952 QRgba64 s = src[i];
1953
1954 uint da = d.alpha();
1955 uint sa = s.alpha();
1956
1957#define OP(a, b) color_dodge_op_rgb64(a, b, da, sa)
1958 uint r = OP( d.red(), s.red());
1959 uint b = OP( d.blue(), s.blue());
1960 uint g = OP(d.green(), s.green());
1961 uint a = mix_alpha_rgb64(da, sa);
1962#undef OP
1963
1964 coverage.store(&dest[i], qRgba64(r, g, b, a));
1965 }
1966}
1967
1968void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
1969{
1970 if (const_alpha == 255)
1971 comp_func_ColorDodge_impl(dest, src, length, coverage: QFullCoverage());
1972 else
1973 comp_func_ColorDodge_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
1974}
1975#endif
1976
1977/*
1978 if Sca.Da + Dca.Sa < Sa.Da
1979 Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
1980 else if Sca == 0
1981 Dca' = Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
1982 otherwise
1983 Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
1984*/
1985static inline int color_burn_op(int dst, int src, int da, int sa)
1986{
1987 const int src_da = src * da;
1988 const int dst_sa = dst * sa;
1989 const int sa_da = sa * da;
1990
1991 const int temp = src * (255 - da) + dst * (255 - sa);
1992
1993 if (src_da + dst_sa < sa_da)
1994 return qt_div_255(x: temp);
1995 else if (src == 0)
1996 return qt_div_255(x: dst_sa + temp);
1997 return qt_div_255(x: sa * (src_da + dst_sa - sa_da) / src + temp);
1998}
1999
2000template <typename T>
2001static inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
2002{
2003 int sa = qAlpha(rgb: color);
2004 int sr = qRed(rgb: color);
2005 int sg = qGreen(rgb: color);
2006 int sb = qBlue(rgb: color);
2007
2008 for (int i = 0; i < length; ++i) {
2009 uint d = dest[i];
2010 int da = qAlpha(rgb: d);
2011
2012#define OP(a, b) color_burn_op(a, b, da, sa)
2013 int r = OP( qRed(d), sr);
2014 int b = OP( qBlue(d), sb);
2015 int g = OP(qGreen(d), sg);
2016 int a = mix_alpha(da, sa);
2017#undef OP
2018
2019 coverage.store(&dest[i], qRgba(r, g, b, a));
2020 }
2021}
2022
2023void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
2024{
2025 if (const_alpha == 255)
2026 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QFullCoverage());
2027 else
2028 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2029}
2030
2031#if QT_CONFIG(raster_64bit)
2032static inline uint color_burn_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
2033{
2034 const qint64 src_da = src * da;
2035 const qint64 dst_sa = dst * sa;
2036 const qint64 sa_da = sa * da;
2037
2038 const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
2039
2040 if (src_da + dst_sa < sa_da)
2041 return qt_div_65535(x: temp);
2042 else if (src == 0)
2043 return qt_div_65535(x: dst_sa + temp);
2044 return qt_div_65535(x: sa * (src_da + dst_sa - sa_da) / src + temp);
2045}
2046
2047template <typename T>
2048static inline void comp_func_solid_ColorBurn_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2049{
2050 uint sa = color.alpha();
2051 uint sr = color.red();
2052 uint sg = color.green();
2053 uint sb = color.blue();
2054
2055 for (int i = 0; i < length; ++i) {
2056 QRgba64 d = dest[i];
2057 uint da = d.alpha();
2058
2059#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
2060 uint r = OP( d.red(), sr);
2061 uint b = OP( d.blue(), sb);
2062 uint g = OP(d.green(), sg);
2063 uint a = mix_alpha_rgb64(da, sa);
2064#undef OP
2065
2066 coverage.store(&dest[i], qRgba64(r, g, b, a));
2067 }
2068}
2069
2070void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2071{
2072 if (const_alpha == 255)
2073 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QFullCoverage());
2074 else
2075 comp_func_solid_ColorBurn_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2076}
2077#endif
2078
2079template <typename T>
2080static inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2081{
2082 for (int i = 0; i < length; ++i) {
2083 uint d = dest[i];
2084 uint s = src[i];
2085
2086 int da = qAlpha(rgb: d);
2087 int sa = qAlpha(rgb: s);
2088
2089#define OP(a, b) color_burn_op(a, b, da, sa)
2090 int r = OP( qRed(d), qRed(s));
2091 int b = OP( qBlue(d), qBlue(s));
2092 int g = OP(qGreen(d), qGreen(s));
2093 int a = mix_alpha(da, sa);
2094#undef OP
2095
2096 coverage.store(&dest[i], qRgba(r, g, b, a));
2097 }
2098}
2099
2100void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2101{
2102 if (const_alpha == 255)
2103 comp_func_ColorBurn_impl(dest, src, length, coverage: QFullCoverage());
2104 else
2105 comp_func_ColorBurn_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2106}
2107
2108#if QT_CONFIG(raster_64bit)
2109template <typename T>
2110static inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2111{
2112 for (int i = 0; i < length; ++i) {
2113 QRgba64 d = dest[i];
2114 QRgba64 s = src[i];
2115
2116 uint da = d.alpha();
2117 uint sa = s.alpha();
2118
2119#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
2120 uint r = OP( d.red(), s.red());
2121 uint b = OP( d.blue(), s.blue());
2122 uint g = OP(d.green(), s.green());
2123 uint a = mix_alpha_rgb64(da, sa);
2124#undef OP
2125
2126 coverage.store(&dest[i], qRgba64(r, g, b, a));
2127 }
2128}
2129
2130void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2131{
2132 if (const_alpha == 255)
2133 comp_func_ColorBurn_impl(dest, src, length, coverage: QFullCoverage());
2134 else
2135 comp_func_ColorBurn_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2136}
2137#endif
2138
2139/*
2140 if 2.Sca < Sa
2141 Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
2142 otherwise
2143 Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
2144*/
2145static inline uint hardlight_op(int dst, int src, int da, int sa)
2146{
2147 const uint temp = src * (255 - da) + dst * (255 - sa);
2148
2149 if (2 * src < sa)
2150 return qt_div_255(x: 2 * src * dst + temp);
2151 else
2152 return qt_div_255(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
2153}
2154
2155template <typename T>
2156static inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
2157{
2158 int sa = qAlpha(rgb: color);
2159 int sr = qRed(rgb: color);
2160 int sg = qGreen(rgb: color);
2161 int sb = qBlue(rgb: color);
2162
2163 for (int i = 0; i < length; ++i) {
2164 uint d = dest[i];
2165 int da = qAlpha(rgb: d);
2166
2167#define OP(a, b) hardlight_op(a, b, da, sa)
2168 int r = OP( qRed(d), sr);
2169 int b = OP( qBlue(d), sb);
2170 int g = OP(qGreen(d), sg);
2171 int a = mix_alpha(da, sa);
2172#undef OP
2173
2174 coverage.store(&dest[i], qRgba(r, g, b, a));
2175 }
2176}
2177
2178void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
2179{
2180 if (const_alpha == 255)
2181 comp_func_solid_HardLight_impl(dest, length, color, coverage: QFullCoverage());
2182 else
2183 comp_func_solid_HardLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2184}
2185
2186#if QT_CONFIG(raster_64bit)
2187static inline uint hardlight_op_rgb64(uint dst, uint src, uint da, uint sa)
2188{
2189 const uint temp = src * (65535 - da) + dst * (65535 - sa);
2190
2191 if (2 * src < sa)
2192 return qt_div_65535(x: 2 * src * dst + temp);
2193 else
2194 return qt_div_65535(x: sa * da - 2 * (da - dst) * (sa - src) + temp);
2195}
2196
2197template <typename T>
2198static inline void comp_func_solid_HardLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2199{
2200 uint sa = color.alpha();
2201 uint sr = color.red();
2202 uint sg = color.green();
2203 uint sb = color.blue();
2204
2205 for (int i = 0; i < length; ++i) {
2206 QRgba64 d = dest[i];
2207 uint da = d.alpha();
2208
2209#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
2210 uint r = OP( d.red(), sr);
2211 uint b = OP( d.blue(), sb);
2212 uint g = OP(d.green(), sg);
2213 uint a = mix_alpha_rgb64(da, sa);
2214#undef OP
2215
2216 coverage.store(&dest[i], qRgba64(r, g, b, a));
2217 }
2218}
2219
2220void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2221{
2222 if (const_alpha == 255)
2223 comp_func_solid_HardLight_impl(dest, length, color, coverage: QFullCoverage());
2224 else
2225 comp_func_solid_HardLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2226}
2227#endif
2228
2229template <typename T>
2230static inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2231{
2232 for (int i = 0; i < length; ++i) {
2233 uint d = dest[i];
2234 uint s = src[i];
2235
2236 int da = qAlpha(rgb: d);
2237 int sa = qAlpha(rgb: s);
2238
2239#define OP(a, b) hardlight_op(a, b, da, sa)
2240 int r = OP( qRed(d), qRed(s));
2241 int b = OP( qBlue(d), qBlue(s));
2242 int g = OP(qGreen(d), qGreen(s));
2243 int a = mix_alpha(da, sa);
2244#undef OP
2245
2246 coverage.store(&dest[i], qRgba(r, g, b, a));
2247 }
2248}
2249
2250void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2251{
2252 if (const_alpha == 255)
2253 comp_func_HardLight_impl(dest, src, length, coverage: QFullCoverage());
2254 else
2255 comp_func_HardLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2256}
2257
2258#if QT_CONFIG(raster_64bit)
2259template <typename T>
2260static inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2261{
2262 for (int i = 0; i < length; ++i) {
2263 QRgba64 d = dest[i];
2264 QRgba64 s = src[i];
2265
2266 uint da = d.alpha();
2267 uint sa = s.alpha();
2268
2269#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
2270 uint r = OP( d.red(), s.red());
2271 uint b = OP( d.blue(), s.blue());
2272 uint g = OP(d.green(), s.green());
2273 uint a = mix_alpha_rgb64(da, sa);
2274#undef OP
2275
2276 coverage.store(&dest[i], qRgba64(r, g, b, a));
2277 }
2278}
2279
2280void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2281{
2282 if (const_alpha == 255)
2283 comp_func_HardLight_impl(dest, src, length, coverage: QFullCoverage());
2284 else
2285 comp_func_HardLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2286}
2287#endif
2288
2289/*
2290 if 2.Sca <= Sa
2291 Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
2292 otherwise if 2.Sca > Sa and 4.Dca <= Da
2293 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)
2294 otherwise if 2.Sca > Sa and 4.Dca > Da
2295 Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
2296*/
2297static inline int soft_light_op(int dst, int src, int da, int sa)
2298{
2299 const int src2 = src << 1;
2300 const int dst_np = da != 0 ? (255 * dst) / da : 0;
2301 const int temp = (src * (255 - da) + dst * (255 - sa)) * 255;
2302
2303 if (src2 < sa)
2304 return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025;
2305 else if (4 * dst <= da)
2306 return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
2307 else {
2308 return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(v: qreal(dst_np * 255))) - dst_np) + temp) / 65025;
2309 }
2310}
2311
2312template <typename T>
2313static inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
2314{
2315 int sa = qAlpha(rgb: color);
2316 int sr = qRed(rgb: color);
2317 int sg = qGreen(rgb: color);
2318 int sb = qBlue(rgb: color);
2319
2320 for (int i = 0; i < length; ++i) {
2321 uint d = dest[i];
2322 int da = qAlpha(rgb: d);
2323
2324#define OP(a, b) soft_light_op(a, b, da, sa)
2325 int r = OP( qRed(d), sr);
2326 int b = OP( qBlue(d), sb);
2327 int g = OP(qGreen(d), sg);
2328 int a = mix_alpha(da, sa);
2329#undef OP
2330
2331 coverage.store(&dest[i], qRgba(r, g, b, a));
2332 }
2333}
2334
2335#if QT_CONFIG(raster_64bit)
2336static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
2337{
2338 const qint64 src2 = src << 1;
2339 const qint64 dst_np = da != 0 ? (65535 * dst) / da : 0;
2340 const qint64 temp = (src * (65535 - da) + dst * (65535 - sa)) * 65535;
2341 const qint64 factor = qint64(65535) * 65535;
2342
2343 if (src2 < sa)
2344 return (dst * (sa * 65535 + (src2 - sa) * (65535 - dst_np)) + temp) / factor;
2345 else if (4 * dst <= da)
2346 return (dst * sa * 65535 + da * (src2 - sa) * ((((16 * dst_np - 12 * 65535) * dst_np + 3 * factor) * dst_np) / factor) + temp) / factor;
2347 else {
2348 return (dst * sa * 65535 + da * (src2 - sa) * (int(qSqrt(v: qreal(dst_np * 65535))) - dst_np) + temp) / factor;
2349 }
2350}
2351
2352template <typename T>
2353static inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2354{
2355 uint sa = color.alpha();
2356 uint sr = color.red();
2357 uint sg = color.green();
2358 uint sb = color.blue();
2359
2360 for (int i = 0; i < length; ++i) {
2361 QRgba64 d = dest[i];
2362 uint da = d.alpha();
2363
2364#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
2365 uint r = OP( d.red(), sr);
2366 uint b = OP( d.blue(), sb);
2367 uint g = OP(d.green(), sg);
2368 uint a = mix_alpha_rgb64(da, sa);
2369#undef OP
2370
2371 coverage.store(&dest[i], qRgba64(r, g, b, a));
2372 }
2373}
2374#endif
2375
2376void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
2377{
2378 if (const_alpha == 255)
2379 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QFullCoverage());
2380 else
2381 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2382}
2383
2384template <typename T>
2385static inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2386{
2387 for (int i = 0; i < length; ++i) {
2388 uint d = dest[i];
2389 uint s = src[i];
2390
2391 int da = qAlpha(rgb: d);
2392 int sa = qAlpha(rgb: s);
2393
2394#define OP(a, b) soft_light_op(a, b, da, sa)
2395 int r = OP( qRed(d), qRed(s));
2396 int b = OP( qBlue(d), qBlue(s));
2397 int g = OP(qGreen(d), qGreen(s));
2398 int a = mix_alpha(da, sa);
2399#undef OP
2400
2401 coverage.store(&dest[i], qRgba(r, g, b, a));
2402 }
2403}
2404
2405void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2406{
2407 if (const_alpha == 255)
2408 comp_func_SoftLight_impl(dest, src, length, coverage: QFullCoverage());
2409 else
2410 comp_func_SoftLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2411}
2412
2413#if QT_CONFIG(raster_64bit)
2414void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2415{
2416 if (const_alpha == 255)
2417 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QFullCoverage());
2418 else
2419 comp_func_solid_SoftLight_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2420}
2421
2422template <typename T>
2423static inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2424{
2425 for (int i = 0; i < length; ++i) {
2426 QRgba64 d = dest[i];
2427 QRgba64 s = src[i];
2428
2429 uint da = d.alpha();
2430 uint sa = s.alpha();
2431
2432#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
2433 uint r = OP( d.red(), s.red());
2434 uint b = OP( d.blue(), s.blue());
2435 uint g = OP(d.green(), s.green());
2436 uint a = mix_alpha_rgb64(da, sa);
2437#undef OP
2438
2439 coverage.store(&dest[i], qRgba64(r, g, b, a));
2440 }
2441}
2442
2443void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2444{
2445 if (const_alpha == 255)
2446 comp_func_SoftLight_impl(dest, src, length, coverage: QFullCoverage());
2447 else
2448 comp_func_SoftLight_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2449}
2450#endif
2451
2452/*
2453 Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
2454 = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
2455*/
2456static inline int difference_op(int dst, int src, int da, int sa)
2457{
2458 return src + dst - qt_div_255(x: 2 * qMin(a: src * da, b: dst * sa));
2459}
2460
2461template <typename T>
2462static inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
2463{
2464 int sa = qAlpha(rgb: color);
2465 int sr = qRed(rgb: color);
2466 int sg = qGreen(rgb: color);
2467 int sb = qBlue(rgb: color);
2468
2469 for (int i = 0; i < length; ++i) {
2470 uint d = dest[i];
2471 int da = qAlpha(rgb: d);
2472
2473#define OP(a, b) difference_op(a, b, da, sa)
2474 int r = OP( qRed(d), sr);
2475 int b = OP( qBlue(d), sb);
2476 int g = OP(qGreen(d), sg);
2477 int a = mix_alpha(da, sa);
2478#undef OP
2479
2480 coverage.store(&dest[i], qRgba(r, g, b, a));
2481 }
2482}
2483
2484void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
2485{
2486 if (const_alpha == 255)
2487 comp_func_solid_Difference_impl(dest, length, color, coverage: QFullCoverage());
2488 else
2489 comp_func_solid_Difference_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2490}
2491
2492#if QT_CONFIG(raster_64bit)
2493static inline uint difference_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
2494{
2495 return src + dst - qt_div_65535(x: 2 * qMin(a: src * da, b: dst * sa));
2496}
2497
2498template <typename T>
2499static inline void comp_func_solid_Difference_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2500{
2501 uint sa = color.alpha();
2502 uint sr = color.red();
2503 uint sg = color.green();
2504 uint sb = color.blue();
2505
2506 for (int i = 0; i < length; ++i) {
2507 QRgba64 d = dest[i];
2508 uint da = d.alpha();
2509
2510#define OP(a, b) difference_op_rgb64(a, b, da, sa)
2511 uint r = OP( d.red(), sr);
2512 uint b = OP( d.blue(), sb);
2513 uint g = OP(d.green(), sg);
2514 uint a = mix_alpha_rgb64(da, sa);
2515#undef OP
2516
2517 coverage.store(&dest[i], qRgba64(r, g, b, a));
2518 }
2519}
2520
2521void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2522{
2523 if (const_alpha == 255)
2524 comp_func_solid_Difference_impl(dest, length, color, coverage: QFullCoverage());
2525 else
2526 comp_func_solid_Difference_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2527}
2528#endif
2529
2530template <typename T>
2531static inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2532{
2533 for (int i = 0; i < length; ++i) {
2534 uint d = dest[i];
2535 uint s = src[i];
2536
2537 int da = qAlpha(rgb: d);
2538 int sa = qAlpha(rgb: s);
2539
2540#define OP(a, b) difference_op(a, b, da, sa)
2541 int r = OP( qRed(d), qRed(s));
2542 int b = OP( qBlue(d), qBlue(s));
2543 int g = OP(qGreen(d), qGreen(s));
2544 int a = mix_alpha(da, sa);
2545#undef OP
2546
2547 coverage.store(&dest[i], qRgba(r, g, b, a));
2548 }
2549}
2550
2551void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2552{
2553 if (const_alpha == 255)
2554 comp_func_Difference_impl(dest, src, length, coverage: QFullCoverage());
2555 else
2556 comp_func_Difference_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2557}
2558
2559#if QT_CONFIG(raster_64bit)
2560template <typename T>
2561static inline void comp_func_Difference_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2562{
2563 for (int i = 0; i < length; ++i) {
2564 QRgba64 d = dest[i];
2565 QRgba64 s = src[i];
2566
2567 uint da = d.alpha();
2568 uint sa = s.alpha();
2569
2570#define OP(a, b) difference_op_rgb64(a, b, da, sa)
2571 uint r = OP( d.red(), s.red());
2572 uint b = OP( d.blue(), s.blue());
2573 uint g = OP(d.green(), s.green());
2574 uint a = mix_alpha_rgb64(da, sa);
2575#undef OP
2576
2577 coverage.store(&dest[i], qRgba64(r, g, b, a));
2578 }
2579}
2580
2581void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2582{
2583 if (const_alpha == 255)
2584 comp_func_Difference_impl(dest, src, length, coverage: QFullCoverage());
2585 else
2586 comp_func_Difference_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2587}
2588#endif
2589
2590/*
2591 Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
2592*/
2593template <typename T>
2594static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
2595{
2596 int sa = qAlpha(rgb: color);
2597 int sr = qRed(rgb: color);
2598 int sg = qGreen(rgb: color);
2599 int sb = qBlue(rgb: color);
2600
2601 for (int i = 0; i < length; ++i) {
2602 uint d = dest[i];
2603 int da = qAlpha(rgb: d);
2604
2605#define OP(a, b) (a + b - qt_div_255(2*(a*b)))
2606 int r = OP( qRed(d), sr);
2607 int b = OP( qBlue(d), sb);
2608 int g = OP(qGreen(d), sg);
2609 int a = mix_alpha(da, sa);
2610#undef OP
2611
2612 coverage.store(&dest[i], qRgba(r, g, b, a));
2613 }
2614}
2615
2616void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
2617{
2618 if (const_alpha == 255)
2619 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QFullCoverage());
2620 else
2621 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2622}
2623
2624#if QT_CONFIG(raster_64bit)
2625template <typename T>
2626static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
2627{
2628 uint sa = color.alpha();
2629 uint sr = color.red();
2630 uint sg = color.green();
2631 uint sb = color.blue();
2632
2633 for (int i = 0; i < length; ++i) {
2634 QRgba64 d = dest[i];
2635 uint da = d.alpha();
2636
2637#define OP(a, b) (a + b - qt_div_65535(2*(qint64(a)*b)))
2638 uint r = OP( d.red(), sr);
2639 uint b = OP( d.blue(), sb);
2640 uint g = OP(d.green(), sg);
2641 uint a = mix_alpha_rgb64(da, sa);
2642#undef OP
2643
2644 coverage.store(&dest[i], qRgba64(r, g, b, a));
2645 }
2646}
2647
2648
2649void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
2650{
2651 if (const_alpha == 255)
2652 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QFullCoverage());
2653 else
2654 comp_func_solid_Exclusion_impl(dest, length, color, coverage: QPartialCoverage(const_alpha));
2655}
2656#endif
2657
2658template <typename T>
2659static inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
2660{
2661 for (int i = 0; i < length; ++i) {
2662 uint d = dest[i];
2663 uint s = src[i];
2664
2665 int da = qAlpha(rgb: d);
2666 int sa = qAlpha(rgb: s);
2667
2668#define OP(a, b) (a + b - ((a*b) >> 7))
2669 int r = OP( qRed(d), qRed(s));
2670 int b = OP( qBlue(d), qBlue(s));
2671 int g = OP(qGreen(d), qGreen(s));
2672 int a = mix_alpha(da, sa);
2673#undef OP
2674
2675 coverage.store(&dest[i], qRgba(r, g, b, a));
2676 }
2677}
2678
2679void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
2680{
2681 if (const_alpha == 255)
2682 comp_func_Exclusion_impl(dest, src, length, coverage: QFullCoverage());
2683 else
2684 comp_func_Exclusion_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2685}
2686
2687#if QT_CONFIG(raster_64bit)
2688template <typename T>
2689static inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
2690{
2691 for (int i = 0; i < length; ++i) {
2692 QRgba64 d = dest[i];
2693 QRgba64 s = src[i];
2694
2695 uint da = d.alpha();
2696 uint sa = s.alpha();
2697
2698#define OP(a, b) (a + b - ((qint64(a)*b) >> 15))
2699 uint r = OP( d.red(), s.red());
2700 uint b = OP( d.blue(), s.blue());
2701 uint g = OP(d.green(), s.green());
2702 uint a = mix_alpha_rgb64(da, sa);
2703#undef OP
2704
2705 coverage.store(&dest[i], qRgba64(r, g, b, a));
2706 }
2707}
2708
2709void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
2710{
2711 if (const_alpha == 255)
2712 comp_func_Exclusion_impl(dest, src, length, coverage: QFullCoverage());
2713 else
2714 comp_func_Exclusion_impl(dest, src, length, coverage: QPartialCoverage(const_alpha));
2715}
2716#endif
2717
2718void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
2719 int length,
2720 uint color,
2721 uint const_alpha)
2722{
2723 Q_UNUSED(const_alpha);
2724 while (length--)
2725 *dest++ |= color;
2726}
2727
2728void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest,
2729 const uint *Q_DECL_RESTRICT src,
2730 int length,
2731 uint const_alpha)
2732{
2733 Q_UNUSED(const_alpha);
2734 while (length--)
2735 *dest++ |= *src++;
2736}
2737
2738void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
2739 int length,
2740 uint color,
2741 uint const_alpha)
2742{
2743 Q_UNUSED(const_alpha);
2744 color |= 0xff000000;
2745 while (length--)
2746 *dest++ &= color;
2747}
2748
2749void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest,
2750 const uint *Q_DECL_RESTRICT src,
2751 int length,
2752 uint const_alpha)
2753{
2754 Q_UNUSED(const_alpha);
2755 while (length--) {
2756 *dest = (*src & *dest) | 0xff000000;
2757 ++dest; ++src;
2758 }
2759}
2760
2761void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
2762 int length,
2763 uint color,
2764 uint const_alpha)
2765{
2766 Q_UNUSED(const_alpha);
2767 color &= 0x00ffffff;
2768 while (length--)
2769 *dest++ ^= color;
2770}
2771
2772void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest,
2773 const uint *Q_DECL_RESTRICT src,
2774 int length,
2775 uint const_alpha)
2776{
2777 Q_UNUSED(const_alpha);
2778 while (length--) {
2779 *dest = (*src ^ *dest) | 0xff000000;
2780 ++dest; ++src;
2781 }
2782}
2783
2784void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
2785 int length,
2786 uint color,
2787 uint const_alpha)
2788{
2789 Q_UNUSED(const_alpha);
2790 color = ~color;
2791 while (length--) {
2792 *dest = (color & ~(*dest)) | 0xff000000;
2793 ++dest;
2794 }
2795}
2796
2797void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
2798 const uint *Q_DECL_RESTRICT src,
2799 int length,
2800 uint const_alpha)
2801{
2802 Q_UNUSED(const_alpha);
2803 while (length--) {
2804 *dest = (~(*src) & ~(*dest)) | 0xff000000;
2805 ++dest; ++src;
2806 }
2807}
2808
2809void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
2810 int length,
2811 uint color,
2812 uint const_alpha)
2813{
2814 Q_UNUSED(const_alpha);
2815 color = ~color | 0xff000000;
2816 while (length--) {
2817 *dest = color | ~(*dest);
2818 ++dest;
2819 }
2820}
2821
2822void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
2823 const uint *Q_DECL_RESTRICT src,
2824 int length,
2825 uint const_alpha)
2826{
2827 Q_UNUSED(const_alpha);
2828 while (length--) {
2829 *dest = ~(*src) | ~(*dest) | 0xff000000;
2830 ++dest; ++src;
2831 }
2832}
2833
2834void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
2835 int length,
2836 uint color,
2837 uint const_alpha)
2838{
2839 Q_UNUSED(const_alpha);
2840 color = ~color & 0x00ffffff;
2841 while (length--) {
2842 *dest = color ^ (*dest);
2843 ++dest;
2844 }
2845}
2846
2847void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest,
2848 const uint *Q_DECL_RESTRICT src,
2849 int length,
2850 uint const_alpha)
2851{
2852 Q_UNUSED(const_alpha);
2853 while (length--) {
2854 *dest = ((~(*src)) ^ (*dest)) | 0xff000000;
2855 ++dest; ++src;
2856 }
2857}
2858
2859void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
2860 uint color, uint const_alpha)
2861{
2862 Q_UNUSED(const_alpha);
2863 qt_memfill(dest, color: ~color | 0xff000000, count: length);
2864}
2865
2866void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src,
2867 int length, uint const_alpha)
2868{
2869 Q_UNUSED(const_alpha);
2870 while (length--)
2871 *dest++ = ~(*src++) | 0xff000000;
2872}
2873
2874void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
2875 int length,
2876 uint color,
2877 uint const_alpha)
2878{
2879 Q_UNUSED(const_alpha);
2880 color = ~color | 0xff000000;
2881 while (length--) {
2882 *dest = color & *dest;
2883 ++dest;
2884 }
2885}
2886
2887void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest,
2888 const uint *Q_DECL_RESTRICT src,
2889 int length,
2890 uint const_alpha)
2891{
2892 Q_UNUSED(const_alpha);
2893 while (length--) {
2894 *dest = (~(*src) & *dest) | 0xff000000;
2895 ++dest; ++src;
2896 }
2897}
2898
2899void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
2900 int length,
2901 uint color,
2902 uint const_alpha)
2903{
2904 Q_UNUSED(const_alpha);
2905 while (length--) {
2906 *dest = (color & ~(*dest)) | 0xff000000;
2907 ++dest;
2908 }
2909}
2910
2911void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
2912 const uint *Q_DECL_RESTRICT src,
2913 int length,
2914 uint const_alpha)
2915{
2916 Q_UNUSED(const_alpha);
2917 while (length--) {
2918 *dest = (*src & ~(*dest)) | 0xff000000;
2919 ++dest; ++src;
2920 }
2921}
2922
2923void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
2924 const uint *Q_DECL_RESTRICT src,
2925 int length,
2926 uint const_alpha)
2927{
2928 Q_UNUSED(const_alpha);
2929 while (length--) {
2930 *dest = (~(*src) | *dest) | 0xff000000;
2931 ++dest; ++src;
2932 }
2933}
2934
2935void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
2936 int length,
2937 uint color,
2938 uint const_alpha)
2939{
2940 Q_UNUSED(const_alpha);
2941 color = ~color | 0xff000000;
2942 while (length--)
2943 *dest++ |= color;
2944}
2945
2946void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
2947 const uint *Q_DECL_RESTRICT src,
2948 int length,
2949 uint const_alpha)
2950{
2951 Q_UNUSED(const_alpha);
2952 while (length--) {
2953 *dest = (*src | ~(*dest)) | 0xff000000;
2954 ++dest; ++src;
2955 }
2956}
2957
2958void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
2959 int length,
2960 uint color,
2961 uint const_alpha)
2962{
2963 Q_UNUSED(const_alpha);
2964 while (length--) {
2965 *dest = (color | ~(*dest)) | 0xff000000;
2966 ++dest;
2967 }
2968}
2969
2970void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest,
2971 const uint *Q_DECL_RESTRICT src,
2972 int length,
2973 uint const_alpha)
2974{
2975 Q_UNUSED(src);
2976 comp_func_solid_SourceOver (dest, length, color: 0xff000000, const_alpha);
2977}
2978
2979void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest,
2980 int length,
2981 uint color,
2982 uint const_alpha)
2983{
2984 Q_UNUSED(color);
2985 comp_func_solid_SourceOver (dest, length, color: 0xff000000, const_alpha);
2986}
2987
2988void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest,
2989 const uint *Q_DECL_RESTRICT src,
2990 int length,
2991 uint const_alpha)
2992{
2993 Q_UNUSED(src);
2994 comp_func_solid_SourceOver (dest, length, color: 0xffffffff, const_alpha);
2995}
2996
2997void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest,
2998 int length,
2999 uint color,
3000 uint const_alpha)
3001{
3002 Q_UNUSED(color);
3003 comp_func_solid_SourceOver (dest, length, color: 0xffffffff, const_alpha);
3004}
3005
3006void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest,
3007 const uint *Q_DECL_RESTRICT src,
3008 int length,
3009 uint const_alpha)
3010{
3011 Q_UNUSED(src);
3012 rasterop_solid_SourceXorDestination (dest, length, color: 0x00ffffff, const_alpha);
3013}
3014
3015void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest,
3016 int length,
3017 uint color,
3018 uint const_alpha)
3019{
3020 Q_UNUSED(color);
3021 rasterop_solid_SourceXorDestination (dest, length, color: 0x00ffffff, const_alpha);
3022}
3023
3024CompositionFunctionSolid qt_functionForModeSolid_C[] = {
3025 comp_func_solid_SourceOver,
3026 comp_func_solid_DestinationOver,
3027 comp_func_solid_Clear,
3028 comp_func_solid_Source,
3029 comp_func_solid_Destination,
3030 comp_func_solid_SourceIn,
3031 comp_func_solid_DestinationIn,
3032 comp_func_solid_SourceOut,
3033 comp_func_solid_DestinationOut,
3034 comp_func_solid_SourceAtop,
3035 comp_func_solid_DestinationAtop,
3036 comp_func_solid_XOR,
3037 comp_func_solid_Plus,
3038 comp_func_solid_Multiply,
3039 comp_func_solid_Screen,
3040 comp_func_solid_Overlay,
3041 comp_func_solid_Darken,
3042 comp_func_solid_Lighten,
3043 comp_func_solid_ColorDodge,
3044 comp_func_solid_ColorBurn,
3045 comp_func_solid_HardLight,
3046 comp_func_solid_SoftLight,
3047 comp_func_solid_Difference,
3048 comp_func_solid_Exclusion,
3049 rasterop_solid_SourceOrDestination,
3050 rasterop_solid_SourceAndDestination,
3051 rasterop_solid_SourceXorDestination,
3052 rasterop_solid_NotSourceAndNotDestination,
3053 rasterop_solid_NotSourceOrNotDestination,
3054 rasterop_solid_NotSourceXorDestination,
3055 rasterop_solid_NotSource,
3056 rasterop_solid_NotSourceAndDestination,
3057 rasterop_solid_SourceAndNotDestination,
3058 rasterop_solid_NotSourceOrDestination,
3059 rasterop_solid_SourceOrNotDestination,
3060 rasterop_solid_ClearDestination,
3061 rasterop_solid_SetDestination,
3062 rasterop_solid_NotDestination
3063};
3064
3065CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
3066#if QT_CONFIG(raster_64bit)
3067 comp_func_solid_SourceOver_rgb64,
3068 comp_func_solid_DestinationOver_rgb64,
3069 comp_func_solid_Clear_rgb64,
3070 comp_func_solid_Source_rgb64,
3071 comp_func_solid_Destination_rgb64,
3072 comp_func_solid_SourceIn_rgb64,
3073 comp_func_solid_DestinationIn_rgb64,
3074 comp_func_solid_SourceOut_rgb64,
3075 comp_func_solid_DestinationOut_rgb64,
3076 comp_func_solid_SourceAtop_rgb64,
3077 comp_func_solid_DestinationAtop_rgb64,
3078 comp_func_solid_XOR_rgb64,
3079 comp_func_solid_Plus_rgb64,
3080 comp_func_solid_Multiply_rgb64,
3081 comp_func_solid_Screen_rgb64,
3082 comp_func_solid_Overlay_rgb64,
3083 comp_func_solid_Darken_rgb64,
3084 comp_func_solid_Lighten_rgb64,
3085 comp_func_solid_ColorDodge_rgb64,
3086 comp_func_solid_ColorBurn_rgb64,
3087 comp_func_solid_HardLight_rgb64,
3088 comp_func_solid_SoftLight_rgb64,
3089 comp_func_solid_Difference_rgb64,
3090 comp_func_solid_Exclusion_rgb64,
3091#else
3092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3094#endif
3095 0, 0, 0, 0, 0, 0,
3096 0, 0, 0, 0, 0, 0, 0, 0
3097};
3098
3099CompositionFunction qt_functionForMode_C[] = {
3100 comp_func_SourceOver,
3101 comp_func_DestinationOver,
3102 comp_func_Clear,
3103 comp_func_Source,
3104 comp_func_Destination,
3105 comp_func_SourceIn,
3106 comp_func_DestinationIn,
3107 comp_func_SourceOut,
3108 comp_func_DestinationOut,
3109 comp_func_SourceAtop,
3110 comp_func_DestinationAtop,
3111 comp_func_XOR,
3112 comp_func_Plus,
3113 comp_func_Multiply,
3114 comp_func_Screen,
3115 comp_func_Overlay,
3116 comp_func_Darken,
3117 comp_func_Lighten,
3118 comp_func_ColorDodge,
3119 comp_func_ColorBurn,
3120 comp_func_HardLight,
3121 comp_func_SoftLight,
3122 comp_func_Difference,
3123 comp_func_Exclusion,
3124 rasterop_SourceOrDestination,
3125 rasterop_SourceAndDestination,
3126 rasterop_SourceXorDestination,
3127 rasterop_NotSourceAndNotDestination,
3128 rasterop_NotSourceOrNotDestination,
3129 rasterop_NotSourceXorDestination,
3130 rasterop_NotSource,
3131 rasterop_NotSourceAndDestination,
3132 rasterop_SourceAndNotDestination,
3133 rasterop_NotSourceOrDestination,
3134 rasterop_SourceOrNotDestination,
3135 rasterop_ClearDestination,
3136 rasterop_SetDestination,
3137 rasterop_NotDestination
3138};
3139
3140CompositionFunction64 qt_functionForMode64_C[] = {
3141#if QT_CONFIG(raster_64bit)
3142 comp_func_SourceOver_rgb64,
3143 comp_func_DestinationOver_rgb64,
3144 comp_func_Clear_rgb64,
3145 comp_func_Source_rgb64,
3146 comp_func_Destination_rgb64,
3147 comp_func_SourceIn_rgb64,
3148 comp_func_DestinationIn_rgb64,
3149 comp_func_SourceOut_rgb64,
3150 comp_func_DestinationOut_rgb64,
3151 comp_func_SourceAtop_rgb64,
3152 comp_func_DestinationAtop_rgb64,
3153 comp_func_XOR_rgb64,
3154 comp_func_Plus_rgb64,
3155 comp_func_Multiply_rgb64,
3156 comp_func_Screen_rgb64,
3157 comp_func_Overlay_rgb64,
3158 comp_func_Darken_rgb64,
3159 comp_func_Lighten_rgb64,
3160 comp_func_ColorDodge_rgb64,
3161 comp_func_ColorBurn_rgb64,
3162 comp_func_HardLight_rgb64,
3163 comp_func_SoftLight_rgb64,
3164 comp_func_Difference_rgb64,
3165 comp_func_Exclusion_rgb64,
3166#else
3167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3169#endif
3170 0, 0, 0, 0, 0, 0,
3171 0, 0, 0, 0, 0, 0, 0, 0
3172};
3173
3174QT_END_NAMESPACE
3175

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