diff options
Diffstat (limited to 'src/gui/painting/qcompositionfunctions.cpp')
-rw-r--r-- | src/gui/painting/qcompositionfunctions.cpp | 1298 |
1 files changed, 1243 insertions, 55 deletions
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp index 65b03a1e12..00fd749fe6 100644 --- a/src/gui/painting/qcompositionfunctions.cpp +++ b/src/gui/painting/qcompositionfunctions.cpp @@ -1,45 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qglobal.h> + #include "qdrawhelper_p.h" #include "qrgba64_p.h" +#include "qrgbafloat.h" QT_BEGIN_NAMESPACE @@ -117,6 +83,8 @@ struct Argb32OperationsC const Argb32OperationsC::Type Argb32OperationsC::clear = 0; +typedef Argb32OperationsC Argb32Operations; + struct Rgba64OperationsBase { typedef QRgba64 Type; @@ -319,9 +287,188 @@ typedef Rgba64OperationsNEON Rgba64Operations; #else typedef Rgba64OperationsC Rgba64Operations; #endif + #endif // QT_CONFIG(raster_64bit) -typedef Argb32OperationsC Argb32Operations; +#if QT_CONFIG(raster_fp) + +static inline QRgbaFloat32 qRgbaFloat32(float r, float g, float b, float a) +{ + return QRgbaFloat32{r, g, b, a}; +} + +struct RgbaFPOperationsBase +{ + typedef QRgbaFloat32 Type; + typedef float Scalar; + + static inline constexpr Type clear = { 0, 0, 0, 0 }; + + static bool isOpaque(Type val) + { return val.a >= 1.0f; } + static bool isTransparent(Type val) + { return val.a <= 0.0f; } + static Scalar scalarFrom8bit(uint8_t a) + { return a * (1.0f / 255.0f); } + + static void memfill(Type *ptr, Type value, qsizetype len) + { + for (qsizetype i = 0; i < len; ++i) + ptr[i] = value; + } + static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len) + { ::memcpy(dest, src, len * sizeof(Type)); } +}; + +struct RgbaFPOperationsC : RgbaFPOperationsBase +{ + typedef QRgbaFloat32 OptimalType; + typedef float OptimalScalar; + + static OptimalType load(const Type *ptr) + { + return QRgbaFloat32 { ptr->r, ptr->g, ptr->b, ptr->a }; + } + static OptimalType convert(const Type &val) + { + return QRgbaFloat32 { val.r, val.g, val.b, val.a }; + } + static void store(Type *ptr, OptimalType value) + { + ptr->r = value.r; + ptr->g = value.g; + ptr->b = value.b; + ptr->a = value.a; + } + static OptimalType add(OptimalType a, OptimalType b) + { + a.r += b.r; + a.g += b.g; + a.b += b.b; + a.a += b.a; + return a; + } + static OptimalScalar add(OptimalScalar a, OptimalScalar b) + { return a + b; } + static OptimalType plus(OptimalType a, OptimalType b) + { + a = add(a, b); // no saturation on color values + if (a.a < 0.0f) a.a = 0.0f; + else if (a.a > 1.0f) a.a = 1.0f; + return a; + } + static OptimalScalar alpha(OptimalType val) + { return val.a; } + static OptimalScalar invAlpha(OptimalScalar c) + { return 1.0f - c; } + static OptimalScalar invAlpha(OptimalType val) + { return 1.0f - val.a; } + static OptimalScalar scalar(Scalar v) + { return v; } + static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a) + { + val.r *= a; + val.g *= a; + val.b *= a; + val.a *= a; + return val; + } + static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a) + { + return val * a * (1.0f / 255.0f); + } + static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2) + { + return add(multiplyAlpha(x, a1), multiplyAlpha(y, a2)); + } + static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a) + { + return multiplyAlpha(val, a * (1.0f / 255.0f)); + } + static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2) + { + return add(multiplyAlpha8bit(x, a1), multiplyAlpha8bit(y, a2)); + } +}; + +#if defined(__SSE2__) +struct RgbaFPOperationsSSE2 : public RgbaFPOperationsBase +{ + typedef __m128 OptimalType; + typedef __m128 OptimalScalar; + + static OptimalType Q_DECL_VECTORCALL load(const Type *ptr) + { + return _mm_loadu_ps(reinterpret_cast<const float *>(ptr)); + } + static OptimalType Q_DECL_VECTORCALL convert(const Type &value) + { + return load(&value); + } + static void Q_DECL_VECTORCALL store(Type *ptr, OptimalType value) + { + _mm_storeu_ps(reinterpret_cast<float *>(ptr), value); + } + static OptimalType Q_DECL_VECTORCALL add(OptimalType a, OptimalType b) + { + return _mm_add_ps(a, b); + } +// same as above: +// static OptimalScalar add(OptimalScalar a, OptimalScalar b) + static OptimalType Q_DECL_VECTORCALL plus(OptimalType a, OptimalType b) + { + a = _mm_add_ps(a, b); + __m128 aa = _mm_min_ps(a, _mm_set1_ps(1.0f)); + aa = _mm_max_ps(aa, _mm_set1_ps(0.0f)); + // An indirect insert using only SSE2: + aa = _mm_shuffle_ps(aa, a, _MM_SHUFFLE(2, 2, 3, 3)); + a = _mm_shuffle_ps(a, aa, _MM_SHUFFLE(0, 2, 1, 0)); + return a; + } + static OptimalScalar Q_DECL_VECTORCALL alpha(OptimalType c) + { + return _mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3)); + } + static OptimalScalar Q_DECL_VECTORCALL invAlpha(Scalar c) + { + return _mm_set1_ps(1.0f - float(c)); + } + static OptimalScalar Q_DECL_VECTORCALL invAlpha(OptimalType c) + { + return _mm_sub_ps(_mm_set1_ps(1.0f), alpha(c)); + } + static OptimalScalar Q_DECL_VECTORCALL scalar(Scalar n) + { + return _mm_set1_ps(float(n)); + } + static OptimalType Q_DECL_VECTORCALL multiplyAlpha(OptimalType val, OptimalScalar a) + { + return _mm_mul_ps(val, a); + } + static OptimalType Q_DECL_VECTORCALL interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2) + { + return add(multiplyAlpha(x, a1), multiplyAlpha(y, a2)); + } + static OptimalType Q_DECL_VECTORCALL multiplyAlpha8bit(OptimalType val, uint8_t a) + { + return multiplyAlpha(val, _mm_set1_ps(a * (1.0f / 255.0f))); + } +// same as above: +// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a) + static OptimalType Q_DECL_VECTORCALL interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2) + { + return add(multiplyAlpha8bit(x, a1), multiplyAlpha8bit(y, a2)); + } +}; +#endif + +#if defined(__SSE2__) +typedef RgbaFPOperationsSSE2 RgbaFPOperations; +#else +typedef RgbaFPOperationsC RgbaFPOperations; +#endif + +#endif // QT_CONFIG(raster_fp) /* result = 0 @@ -362,6 +509,17 @@ void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int lengt } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_Clear_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32, uint const_alpha) +{ + comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha); +} + +void QT_FASTCALL comp_func_Clear_rgbafp(QRgbaFloat32 *dest, const QRgbaFloat32 *, int length, uint const_alpha) +{ + comp_func_Clear_template<RgbaFPOperations>(dest, length, const_alpha); +} +#endif /* result = s @@ -421,6 +579,18 @@ void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRg } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_Source_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_Source_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_Source_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_Source_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) { } @@ -439,6 +609,16 @@ void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, ui } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_Destination_rgbafp(QRgbaFloat32 *, int, QRgbaFloat32, uint) +{ +} + +void QT_FASTCALL comp_func_Destination_rgbafp(QRgbaFloat32 *, const QRgbaFloat32 *, int, uint) +{ +} +#endif + /* result = s + d * sia dest = (s + d * sia) * ca + d * cia @@ -509,6 +689,19 @@ void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_SourceOver_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_SourceOver_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + + +void QT_FASTCALL comp_func_SourceOver_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_SourceOver_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = d + s * dia dest = (d + s * dia) * ca + d * cia @@ -570,6 +763,18 @@ void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_DestinationOver_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_DestinationOver_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_DestinationOver_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_DestinationOver_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = s * da dest = s * da * ca + d * cia @@ -636,6 +841,18 @@ void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_SourceIn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_SourceIn_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_SourceIn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_SourceIn_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = d * sa dest = d * sa * ca + d * cia @@ -697,6 +914,18 @@ void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, co } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_DestinationIn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_DestinationIn_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_DestinationIn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_DestinationIn_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = s * dia dest = s * dia * ca + d * cia @@ -761,6 +990,18 @@ void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_SourceOut_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_SourceOut_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_SourceOut_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_SourceOut_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = d * sia dest = d * sia * ca + d * cia @@ -822,6 +1063,18 @@ void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, c } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_DestinationOut_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_DestinationOut_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_DestinationOut_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_DestinationOut_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = s*da + d*sia dest = s*da*ca + d*sia*ca + d *cia @@ -883,6 +1136,18 @@ void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_SourceAtop_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_SourceAtop_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_SourceAtop_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_SourceAtop_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = d*sa + s*dia dest = d*sa*ca + s*dia*ca + d *cia @@ -949,6 +1214,18 @@ void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_DestinationAtop_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_DestinationAtop_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_DestinationAtop_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_DestinationAtop_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* result = d*sia + s*dia dest = d*sia*ca + s*dia*ca + d *cia @@ -1011,15 +1288,35 @@ void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba6 } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_XOR_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_XOR_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_XOR_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_XOR_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + struct QFullCoverage { inline void store(uint *dest, const uint src) const { *dest = src; } +#if QT_CONFIG(raster_64bit) inline void store(QRgba64 *dest, const QRgba64 src) const { *dest = src; } +#endif +#if QT_CONFIG(raster_fp) + inline void store(QRgbaFloat32 *dest, const QRgbaFloat32 src) const + { + *dest = src; + } +#endif }; struct QPartialCoverage { @@ -1029,14 +1326,27 @@ struct QPartialCoverage { { } + template<typename Op> + inline void store_template(typename Op::Type *dest, const typename Op::Type src) const + { + Op::store(dest, Op::interpolate8bit(Op::convert(src), ca, Op::load(dest), ica)); + } inline void store(uint *dest, const uint src) const { - *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica); + store_template<Argb32Operations>(dest, src); } +#if QT_CONFIG(raster_64bit) inline void store(QRgba64 *dest, const QRgba64 src) const { - *dest = interpolate255(src, ca, *dest, ica); + store_template<Rgba64Operations>(dest, src); + } +#endif +#if QT_CONFIG(raster_fp) + inline void store(QRgbaFloat32 *dest, const QRgbaFloat32 src) const + { + store_template<RgbaFPOperations>(dest, src); } +#endif private: const uint ca; @@ -1045,13 +1355,22 @@ private: static inline int mix_alpha(int da, int sa) { - return 255 - ((255 - sa) * (255 - da) >> 8); + return 255 - qt_div_255((255 - sa) * (255 - da)); } +#if QT_CONFIG(raster_64bit) static inline uint mix_alpha_rgb64(uint da, uint sa) { - return 65535U - ((65535U - sa) * (65535U - da) >> 16); + return 65535U - qt_div_65535((65535U - sa) * (65535U - da)); +} +#endif + +#if QT_CONFIG(raster_fp) +static inline float mix_alpha_rgbafp(float da, float sa) +{ + return 1.0f - (1.0f - sa) * (1.0f - da); } +#endif /* Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa) @@ -1122,6 +1441,18 @@ void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba } #endif +#if QT_CONFIG(raster_fp) +void QT_FASTCALL comp_func_solid_Plus_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + comp_func_solid_Plus_template<RgbaFPOperations>(dest, length, color, const_alpha); +} + +void QT_FASTCALL comp_func_Plus_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + comp_func_Plus_template<RgbaFPOperations>(dest, src, length, const_alpha); +} +#endif + /* Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) */ @@ -1199,6 +1530,45 @@ void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba } #endif +#if QT_CONFIG(raster_fp) +static inline float multiply_op_rgbafp(float dst, float src, float da, float sa) +{ + return src * dst + src * (1.0f - da) + dst * (1.0f - sa); +} + +template <typename T> +static inline void comp_func_solid_Multiply_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) multiply_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Multiply_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + + template <typename T> static inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1259,6 +1629,37 @@ void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Multiply_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) multiply_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Multiply_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Multiply_impl(dest, src, length, QFullCoverage()); + else + comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) = Sca + Dca - Sca.Dca @@ -1327,6 +1728,39 @@ void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64 } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_solid_Screen_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b))) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Screen_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Screen_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1337,7 +1771,7 @@ static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint int da = qAlpha(d); int sa = qAlpha(s); -#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8) +#define OP(a, b) 255 - qt_div_255((255-a) * (255-b)) int r = OP( qRed(d), qRed(s)); int b = OP( qBlue(d), qBlue(s)); int g = OP(qGreen(d), qGreen(s)); @@ -1367,7 +1801,7 @@ static inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QR uint da = d.alpha(); uint sa = s.alpha(); -#define OP(a, b) 65535U - (((65535U-a) * (65535U-b)) >> 16) +#define OP(a, b) 65535U - qt_div_65535((65535U-a) * (65535U-b)) uint r = OP( d.red(), s.red()); uint b = OP( d.blue(), s.blue()); uint g = OP(d.green(), s.green()); @@ -1387,6 +1821,37 @@ void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int l } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Screen_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) (1.0f - ((1.0f - a) * (1.0f - b))) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Screen_rgbafp(QRgbaFloat32 *dest, const QRgbaFloat32 *src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Screen_impl(dest, src, length, QFullCoverage()); + else + comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* if 2.Dca < Da Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) @@ -1475,6 +1940,48 @@ void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba6 } #endif +#if QT_CONFIG(raster_fp) +static inline float overlay_op_rgbafp(float dst, float src, float da, float sa) +{ + const float temp = src * (1.0f - da) + dst * (1.0f - sa); + if (2 * dst < da) + return 2 * src * dst + temp; + else + return sa * da - 2 * (da - dst) * (sa - src) + temp; +} + +template <typename T> +static inline void comp_func_solid_Overlay_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) overlay_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Overlay_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1535,6 +2042,37 @@ void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Overlay_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) overlay_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Overlay_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Overlay_impl(dest, src, length, QFullCoverage()); + else + comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) Da' = Sa + Da - Sa.Da @@ -1613,6 +2151,44 @@ void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64 } #endif +#if QT_CONFIG(raster_fp) +static inline float darken_op_rgbafp(float dst, float src, float da, float sa) +{ + return qMin(src * da, dst * sa) + src * (1.0f - da) + dst * (1.0f - sa); +} + +template <typename T> +static inline void comp_func_solid_Darken_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) darken_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Darken_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Darken_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1673,6 +2249,37 @@ void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRg } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Darken_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) darken_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Darken_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Darken_impl(dest, src, length, QFullCoverage()); + else + comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) Da' = Sa + Da - Sa.Da @@ -1752,6 +2359,44 @@ void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba6 } #endif +#if QT_CONFIG(raster_fp) +static inline float lighten_op_rgbafp(float dst, float src, float da, float sa) +{ + return qMax(src * da, dst * sa) + src * (1.0f - da) + dst * (1.0f - sa); +} + +template <typename T> +static inline void comp_func_solid_Lighten_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) lighten_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Lighten_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1812,6 +2457,37 @@ void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QR } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Lighten_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) lighten_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Lighten_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Lighten_impl(dest, src, length, QFullCoverage()); + else + comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* if Sca.Da + Dca.Sa > Sa.Da Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) @@ -1914,6 +2590,54 @@ void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRg } #endif +#if QT_CONFIG(raster_fp) +static inline float color_dodge_op_rgbafp(float dst, float src, float da, float sa) +{ + const float sa_da = sa * da; + const float dst_sa = dst * sa; + const float src_da = src * da; + + const float temp = src * (1.0f - da) + dst * (1.0f - sa); + if (src_da + dst_sa > sa_da) + return sa_da + temp; + else if (src == sa || sa == 0.0f) + return temp; + else + return dst_sa / (1.0f - src / sa) + temp; +} + +template <typename T> +static inline void comp_func_solid_ColorDodge_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a,b) color_dodge_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_ColorDodge_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -1974,6 +2698,37 @@ void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_ColorDodge_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) color_dodge_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_ColorDodge_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_ColorDodge_impl(dest, src, length, QFullCoverage()); + else + comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* if Sca.Da + Dca.Sa < Sa.Da Dca' = Sca.(1 - Da) + Dca.(1 - Sa) @@ -2076,6 +2831,54 @@ void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgb } #endif +#if QT_CONFIG(raster_fp) +static inline float color_burn_op_rgbafp(float dst, float src, float da, float sa) +{ + const float src_da = src * da; + const float dst_sa = dst * sa; + const float sa_da = sa * da; + + const float temp = src * (1.0f - da) + dst * (1.0f - sa); + + if (src_da + dst_sa < sa_da) + return temp; + else if (src == 0) + return dst_sa + temp; + return sa * (src_da + dst_sa - sa_da) / src + temp; +} + +template <typename T> +static inline void comp_func_solid_ColorBurn_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_ColorBurn_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -2136,6 +2939,37 @@ void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_ColorBurn_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) color_burn_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_ColorBurn_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_ColorBurn_impl(dest, src, length, QFullCoverage()); + else + comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* if 2.Sca < Sa Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) @@ -2226,6 +3060,49 @@ void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgb } #endif +#if QT_CONFIG(raster_fp) +static inline float hardlight_op_rgbafp(float dst, float src, float da, float sa) +{ + const float temp = src * (1.0f - da) + dst * (1.0f - sa); + + if (2 * src < sa) + return 2 * src * dst + temp; + else + return sa * da - 2 * (da - dst) * (sa - src) + temp; +} + +template <typename T> +static inline void comp_func_solid_HardLight_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_HardLight_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -2286,6 +3163,37 @@ void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_HardLight_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) hardlight_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_HardLight_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_HardLight_impl(dest, src, length, QFullCoverage()); + else + comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* if 2.Sca <= Sa Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) @@ -2332,6 +3240,14 @@ static inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint c } } +void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + #if QT_CONFIG(raster_64bit) static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa) { @@ -2371,15 +3287,64 @@ static inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRg coverage.store(&dest[i], qRgba64(r, g, b, a)); } } + +void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); +} + #endif -void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) +#if QT_CONFIG(raster_fp) +static inline float soft_light_op_rgbafp(float dst, float src, float da, float sa) +{ + const float src2 = src * 2; + const float dst_np = da != 0.0f ? (dst / da) : 0.0f; + const float temp = src * (1.0f - da) + dst * (1.0f - sa); + + if (src2 < sa) + return dst * (sa + (src2 - sa) * (1.0f - dst_np)) + temp; + else if (4 * dst <= da) + return dst * sa + da * (src2 - sa) * (((16 * dst_np - 12) * dst_np + 3) * dst_np) + temp; + else { + return dst * sa + da * (src2 - sa) * (qSqrt(qreal(dst_np)) - dst_np) + temp; + } +} + +template <typename T> +static inline void comp_func_solid_SoftLight_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_SoftLight_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) { if (const_alpha == 255) comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); else comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); } +#endif template <typename T> static inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) @@ -2411,14 +3376,6 @@ void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_D } #if QT_CONFIG(raster_64bit) -void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) -{ - if (const_alpha == 255) - comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); - else - comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); -} - template <typename T> static inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -2449,6 +3406,37 @@ void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_SoftLight_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) soft_light_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_SoftLight_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_SoftLight_impl(dest, src, length, QFullCoverage()); + else + comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) = Sca + Dca - 2.min(Sca.Da, Dca.Sa) @@ -2527,6 +3515,44 @@ void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRg } #endif +#if QT_CONFIG(raster_fp) +static inline float difference_op_rgbafp(float dst, float src, float da, float sa) +{ + return src + dst - (2 * qMin(src * da, dst * sa)); +} + +template <typename T> +static inline void comp_func_solid_Difference_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) difference_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Difference_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Difference_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -2587,6 +3613,37 @@ void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Difference_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) difference_op_rgbafp(a, b, da, sa) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Difference_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Difference_impl(dest, src, length, QFullCoverage()); + else + comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + /* Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) */ @@ -2645,7 +3702,6 @@ static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int } } - void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) { if (const_alpha == 255) @@ -2655,6 +3711,39 @@ void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgb } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, const T &coverage) +{ + float sa = color.alpha(); + float sr = color.red(); + float sg = color.green(); + float sb = color.blue(); + + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + float da = d.alpha(); + +#define OP(a, b) (a + b - (2.0f * a * b)) + float r = OP( d.red(), sr); + float b = OP( d.blue(), sb); + float g = OP(d.green(), sg); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_solid_Exclusion_rgbafp(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage()); + else + comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha)); +} +#endif + template <typename T> static inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage) { @@ -2715,6 +3804,37 @@ void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const } #endif +#if QT_CONFIG(raster_fp) +template <typename T> +static inline void comp_func_Exclusion_impl(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, const T &coverage) +{ + for (int i = 0; i < length; ++i) { + QRgbaFloat32 d = dest[i]; + QRgbaFloat32 s = src[i]; + + float da = d.alpha(); + float sa = s.alpha(); + +#define OP(a, b) (a + b - (2.0f * a * b)) + float r = OP( d.red(), s.red()); + float b = OP( d.blue(), s.blue()); + float g = OP(d.green(), s.green()); + float a = mix_alpha_rgbafp(da, sa); +#undef OP + + coverage.store(&dest[i], qRgbaFloat32(r, g, b, a)); + } +} + +void QT_FASTCALL comp_func_Exclusion_rgbafp(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + comp_func_Exclusion_impl(dest, src, length, QFullCoverage()); + else + comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); +} +#endif + void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, @@ -3097,6 +4217,40 @@ CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; +CompositionFunctionSolidFP qt_functionForModeSolidFP_C[] = { +#if QT_CONFIG(raster_fp) + comp_func_solid_SourceOver_rgbafp, + comp_func_solid_DestinationOver_rgbafp, + comp_func_solid_Clear_rgbafp, + comp_func_solid_Source_rgbafp, + comp_func_solid_Destination_rgbafp, + comp_func_solid_SourceIn_rgbafp, + comp_func_solid_DestinationIn_rgbafp, + comp_func_solid_SourceOut_rgbafp, + comp_func_solid_DestinationOut_rgbafp, + comp_func_solid_SourceAtop_rgbafp, + comp_func_solid_DestinationAtop_rgbafp, + comp_func_solid_XOR_rgbafp, + comp_func_solid_Plus_rgbafp, + comp_func_solid_Multiply_rgbafp, + comp_func_solid_Screen_rgbafp, + comp_func_solid_Overlay_rgbafp, + comp_func_solid_Darken_rgbafp, + comp_func_solid_Lighten_rgbafp, + comp_func_solid_ColorDodge_rgbafp, + comp_func_solid_ColorBurn_rgbafp, + comp_func_solid_HardLight_rgbafp, + comp_func_solid_SoftLight_rgbafp, + comp_func_solid_Difference_rgbafp, + comp_func_solid_Exclusion_rgbafp, +#else + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#endif + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + CompositionFunction qt_functionForMode_C[] = { comp_func_SourceOver, comp_func_DestinationOver, @@ -3173,4 +4327,38 @@ CompositionFunction64 qt_functionForMode64_C[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; +CompositionFunctionFP qt_functionForModeFP_C[] = { +#if QT_CONFIG(raster_fp) + comp_func_SourceOver_rgbafp, + comp_func_DestinationOver_rgbafp, + comp_func_Clear_rgbafp, + comp_func_Source_rgbafp, + comp_func_Destination_rgbafp, + comp_func_SourceIn_rgbafp, + comp_func_DestinationIn_rgbafp, + comp_func_SourceOut_rgbafp, + comp_func_DestinationOut_rgbafp, + comp_func_SourceAtop_rgbafp, + comp_func_DestinationAtop_rgbafp, + comp_func_XOR_rgbafp, + comp_func_Plus_rgbafp, + comp_func_Multiply_rgbafp, + comp_func_Screen_rgbafp, + comp_func_Overlay_rgbafp, + comp_func_Darken_rgbafp, + comp_func_Lighten_rgbafp, + comp_func_ColorDodge_rgbafp, + comp_func_ColorBurn_rgbafp, + comp_func_HardLight_rgbafp, + comp_func_SoftLight_rgbafp, + comp_func_Difference_rgbafp, + comp_func_Exclusion_rgbafp, +#else + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#endif + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + QT_END_NAMESPACE |