summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qcompositionfunctions.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-08 16:36:11 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-04-06 08:18:53 +0000
commit54dcbf49927954e913c1f65d2c67396f0bec14f9 (patch)
treeb1cd4718a01cd0b51941a95836dac71b080bbdf6 /src/gui/painting/qcompositionfunctions.cpp
parent5a20a1d7807426f21cf553bb56215c1fae0df6ca (diff)
Generalize composition functions
Change the composition functions upto and including comp_func_plus to a templated structure sharing implementations. Change-Id: I14bcb4b28870aacffce78f372589fdebbaf12ecf Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/painting/qcompositionfunctions.cpp')
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp1094
1 files changed, 640 insertions, 454 deletions
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 339a9749b8..027bf23115 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -64,125 +64,354 @@ QT_BEGIN_NAMESPACE
where the source is an array of pixels.
*/
-#if defined __SSE2__
-# define LOAD(ptr) _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr))
+struct Argb32OperationsC
+{
+ typedef QRgb Type;
+ typedef quint8 Scalar;
+ typedef QRgb OptimalType;
+ typedef quint8 OptimalScalar;
+
+ static const Type clear;
+ static bool isOpaque(Type val)
+ { return qAlpha(val) == 255; }
+ static bool isTransparent(Type val)
+ { return qAlpha(val) == 0; }
+ static Scalar scalarFrom8bit(uint8_t a)
+ { return a; }
+ static void memfill(Type *ptr, Type value, qsizetype len)
+ { qt_memfill32(ptr, value, len); }
+ static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
+ { ::memcpy(dest, src, len * sizeof(Type)); }
+
+ static OptimalType load(const Type *ptr)
+ { return *ptr; }
+ static OptimalType convert(const Type &val)
+ { return val; }
+ static void store(Type *ptr, OptimalType value)
+ { *ptr = value; }
+ static OptimalType add(OptimalType a, OptimalType b)
+ { return a + b; }
+ static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ { return a + b; }
+ static OptimalType plus(OptimalType a, OptimalType b)
+ { return comp_func_Plus_one_pixel(a, b); }
+ static OptimalScalar alpha(OptimalType val)
+ { return qAlpha(val); }
+ static OptimalScalar invAlpha(OptimalScalar c)
+ { return 255 - c; }
+ static OptimalScalar invAlpha(OptimalType val)
+ { return alpha(~val); }
+ static OptimalScalar scalar(Scalar v)
+ { return v; }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ { return BYTE_MUL(val, a); }
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ { return INTERPOLATE_PIXEL_255(x, a1, y, a2); }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ { return BYTE_MUL(val, a); }
+ static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
+ { return qt_div_255(val * a); }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ { return INTERPOLATE_PIXEL_255(x, a1, y, a2); }
+};
+
+const Argb32OperationsC::Type Argb32OperationsC::clear = 0;
+
+struct Rgba64OperationsBase
+{
+ typedef QRgba64 Type;
+ typedef quint16 Scalar;
+
+ static const Type clear;
+
+ static bool isOpaque(Type val)
+ { return val.isOpaque(); }
+ static bool isTransparent(Type val)
+ { return val.isTransparent(); }
+ static Scalar scalarFrom8bit(uint8_t a)
+ { return a * 257; }
+
+ static void memfill(Type *ptr, Type value, qsizetype len)
+ { qt_memfill64((quint64*)ptr, value, len); }
+ static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
+ { ::memcpy(dest, src, len * sizeof(Type)); }
+};
+
+const Rgba64OperationsBase::Type Rgba64OperationsBase::clear = QRgba64::fromRgba64(0);
+
+struct Rgba64OperationsC : public Rgba64OperationsBase
+{
+ typedef QRgba64 OptimalType;
+ typedef quint16 OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ { return *ptr; }
+ static OptimalType convert(const Type &val)
+ { return val; }
+ static void store(Type *ptr, OptimalType value)
+ { *ptr = value; }
+ static OptimalType add(OptimalType a, OptimalType b)
+ { return QRgba64::fromRgba64((quint64)a + (quint64)b); }
+ static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ { return a + b; }
+ static OptimalType plus(OptimalType a, OptimalType b)
+ { return addWithSaturation(a, b); }
+ static OptimalScalar alpha(OptimalType val)
+ { return val.alpha(); }
+ static OptimalScalar invAlpha(Scalar c)
+ { return 65535 - c; }
+ static OptimalScalar invAlpha(OptimalType val)
+ { return 65535 - alpha(val); }
+ static OptimalScalar scalar(Scalar v)
+ { return v; }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ { return multiplyAlpha255(val, a); }
+ static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
+ { return qt_div_255(val * a); }
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ { return interpolate255(x, a1, y, a2); }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ { return multiplyAlpha65535(val, a); }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ { return interpolate65535(x, a1, y, a2); }
+};
+
+#if defined(__SSE2__)
+struct Rgba64OperationsSSE2 : public Rgba64OperationsBase
+{
+ typedef __m128i OptimalType;
+ typedef __m128i OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ }
+ static OptimalType convert(const Type &value)
+ {
#ifdef Q_PROCESSOR_X86_64
-# define CONVERT(value) _mm_cvtsi64_si128(value)
+ return _mm_cvtsi64_si128(value);
#else
-# define CONVERT(value) LOAD(&value)
+ return load(&value);
#endif
-# define STORE(ptr, value) _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr), value)
-# define ADD(p, q) _mm_add_epi32(p, q)
-# define ALPHA(c) _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3))
-# define CONST(n) _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0))
-# define INVALPHA(c) _mm_sub_epi32(CONST(65535), ALPHA(c))
-#elif defined __ARM_NEON__
-# define LOAD(ptr) vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)))
-# define CONVERT(value) vreinterpret_u16_u64(vmov_n_u64(value))
-# define STORE(ptr, value) vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value))
-# define ADD(p, q) vadd_u16(p, q)
-# define ALPHA(c) vdup_lane_u16(c, 3)
-# define CONST(n) vdup_n_u16(n)
-# define INVALPHA(c) vmvn_u16(ALPHA(c))
-#else
-# define LOAD(ptr) *ptr
-# define CONVERT(value) value
-# define STORE(ptr, value) *ptr = value
-# define ADD(p, q) (p + q)
-# define ALPHA(c) (c).alpha()
-# define CONST(n) n
-# define INVALPHA(c) (65535 - ALPHA(c))
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr), value);
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return _mm_add_epi16(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ return _mm_adds_epu16(a, b);
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ return _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3));
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return scalar(65535 - c);
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return _mm_xor_si128(_mm_set1_epi16(-1), alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ return _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0));
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha255(val, a);
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return interpolate255(x, a1, y, a2);
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return multiplyAlpha65535(val, a);
+ }
+ // a2 is const-ref because otherwise MSVC2015@x86 complains that it can't 16-byte align the argument.
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, const OptimalScalar &a2)
+ {
+ return interpolate65535(x, a1, y, a2);
+ }
+};
#endif
+#if defined(__ARM_NEON__)
+struct Rgba64OperationsNEON : public Rgba64OperationsBase
+{
+ typedef uint16x4_t OptimalType;
+ typedef uint16x4_t OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)));
+ }
+ static OptimalType convert(const Type &val)
+ {
+ return vreinterpret_u16_u64(vmov_n_u64(val));
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value));
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return vadd_u16(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ return vqadd_u16(a, b);
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ return vdup_lane_u16(c, 3);
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return scalar(65535 - c);
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return vmvn_u16(alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ return vdup_n_u16(n);
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha255(val, a);
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return interpolate255(x, a1, y, a2);
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return multiplyAlpha65535(val, a);
+ }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ {
+ return interpolate65535(x, a1, y, a2);
+ }
+};
+
+#endif
+
+typedef Argb32OperationsC Argb32Operations;
+#if defined(__SSE2__)
+typedef Rgba64OperationsSSE2 Rgba64Operations;
+#elif defined(__ARM_NEON__)
+typedef Rgba64OperationsNEON Rgba64Operations;
+#else
+typedef Rgba64OperationsC Rgba64Operations;
+#endif
/*
result = 0
d = d * cia
*/
-void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Clear_template(typename Ops::Type *dest, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill32(dest, 0, length);
- } else {
+ if (const_alpha == 255)
+ Ops::memfill(dest, Ops::clear, length);
+ else {
uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
- dest[i] = BYTE_MUL(dest[i], ialpha);
+ for (int i = 0; i < length; ++i) {
+ Ops::store(&dest[i], Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha));
+ }
}
}
+void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+{
+ comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill64((quint64*)dest, 0, length);
- } else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
- STORE(&dest[i], multiplyAlpha255(LOAD(&dest[i]), ialpha));
- }
+ comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
{
- comp_func_solid_Clear(dest, length, 0, const_alpha);
+ comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
}
void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
{
- comp_func_solid_Clear_rgb64(dest, length, QRgba64(), const_alpha);
+ comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
/*
result = s
dest = s * ca + d * cia
*/
-void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_Source_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill32(dest, color, length);
- } else {
- uint ialpha = 255 - const_alpha;
- color = BYTE_MUL(color, const_alpha);
+ if (const_alpha == 255)
+ Ops::memfill(dest, color, length);
+ else {
+ const uint ialpha = 255 - const_alpha;
+ auto s = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
for (int i = 0; i < length; ++i) {
- dest[i] = color + BYTE_MUL(dest[i], ialpha);
+ auto d = Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha);
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
-void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Source_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255)
- qt_memfill64((quint64*)dest, color, length);
+ Ops::memcpy(dest, src, length);
else {
- uint ialpha = 255 - const_alpha;
- auto c = multiplyAlpha255(CONVERT(color), const_alpha);
+ const uint ialpha = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], ADD(c, multiplyAlpha255(LOAD(&dest[i]), ialpha)));
+ auto s = Ops::load(src + i);
+ auto d = Ops::load(dest + i);
+ Ops::store(&dest[i], Ops::interpolate8bit(s, const_alpha, d, ialpha));
}
}
}
+void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- ::memcpy(dest, src, size_t(length) * sizeof(uint));
- } else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
- }
- }
+ comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255)
- ::memcpy(dest, src, size_t(length) * sizeof(quint64));
- else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], interpolate255(LOAD(&src[i]), const_alpha, LOAD(&dest[i]), ialpha));
- }
- }
+ comp_func_Source_template<Rgba64Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
@@ -207,68 +436,66 @@ void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, ui
= s * ca + d * (sia * ca + cia)
= s * ca + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- if ((const_alpha & qAlpha(color)) == 255) {
- qt_memfill32(dest, color, length);
- } else {
+ if (const_alpha == 255 && Ops::isOpaque(color))
+ Ops::memfill(dest, color, length);
+ else {
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto cAlpha = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), cAlpha);
+ Ops::store(&dest[i], Ops::add(c, d));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
- if (const_alpha == 255 && color.isOpaque()) {
- qt_memfill64((quint64*)dest, color, length);
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ auto c = src[i];
+ if (Ops::isOpaque(c))
+ Ops::store(&dest[i], Ops::convert(c));
+ else if (!Ops::isTransparent(c)) {
+ auto s = Ops::convert(c);
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
+ Ops::store(&dest[i], Ops::add(s, d));
+ }
+ }
} else {
- auto c = CONVERT(color);
- if (const_alpha != 255)
- c = multiplyAlpha255(c, const_alpha);
- auto cAlpha = INVALPHA(c);
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], ADD(c, multiplyAlpha65535(LOAD(&dest[i]), cAlpha)));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- uint s = src[i];
- if (s >= 0xff000000)
- dest[i] = s;
- else if (s != 0)
- dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
- }
- }
+ comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- if (s.isOpaque())
- dest[i] = s;
- else if (!s.isTransparent())
- STORE(&dest[i], ADD(CONVERT(s), multiplyAlpha65535(LOAD(&dest[i]), 65535 - s.alpha())));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], ADD(s, multiplyAlpha65535(LOAD(&dest[i]), INVALPHA(s))));
- }
- }
+ comp_func_SourceOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -276,128 +503,122 @@ void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = (d + s * dia) * ca + d * cia
= d + s * dia * ca
*/
-void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = d + BYTE_MUL(color, qAlpha(~d));
- }
-}
-
-void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- auto c = CONVERT(color);
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- c = multiplyAlpha255(c, const_alpha);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(c, INVALPHA(d))));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(c, Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
-void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(Ops::load(&src[i]), Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
} else {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = d + BYTE_MUL(s, qAlpha(~d));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ s = Ops::multiplyAlpha(s, Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationOver_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(LOAD(&src[i]), INVALPHA(d))));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(s, INVALPHA(d))));
- }
- }
+ comp_func_DestinationOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
result = s * da
dest = s * da * ca + d * cia
*/
-void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
if (const_alpha == 255) {
+ auto c = Ops::convert(color);
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::alpha(Ops::load(&dest[i]))));
}
} else {
- color = BYTE_MUL(color, const_alpha);
- uint cia = 255 - const_alpha;
+ auto c = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, cia));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
- auto c = CONVERT(color);
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(c, dest[i].alpha()));
+ auto s = Ops::load(&src[i]);
+ Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::alpha(Ops::load(&dest[i]))));
}
} else {
- uint ca = const_alpha * 257;
- auto cia = CONST(65535 - ca);
- auto c = multiplyAlpha65535(CONVERT(color), ca);
+ auto ca = Ops::scalarFrom8bit(const_alpha);
+ auto cia = Ops::invAlpha(ca);
+ auto cav = Ops::scalar(ca);
for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], interpolate65535(c, ALPHA(d), d, cia));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(Ops::load(&src[i]), cav);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, cia));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceIn_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
- }
- } else {
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
- }
- }
+ comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&src[i]), dest[i].alpha()));
- }
- } else {
- uint ca = const_alpha * 257;
- auto cia = CONST(65535 - ca);
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha65535(LOAD(&src[i]), ca);
- STORE(&dest[i], interpolate65535(s, ALPHA(d), d, cia));
- }
- }
+ comp_func_SourceIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -405,128 +626,120 @@ void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q
dest = d * sa * ca + d * cia
= d * (sa * ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(color);
+ auto sa = Ops::alpha(Ops::convert(color));
if (const_alpha != 255) {
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- }
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], a);
+ sa = Ops::multiplyAlpha8bit(sa, const_alpha);
+ sa = Ops::add(sa, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
}
-}
-void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = color.alpha();
- uint ca64k = const_alpha * 257;
- if (const_alpha != 255)
- a = qt_div_65535(a * ca64k) + 65535 - ca64k;
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), a));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
}
}
-void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
+ auto a = Ops::alpha(Ops::load(&src[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), a));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], a);
+ auto sa = Ops::multiplyAlpha8bit(Ops::alpha(Ops::load(&src[i])), const_alpha);
+ sa = Ops::add(sa, cia);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationIn_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), src[i].alpha()));
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- uint a = qt_div_65535(src[i].alpha() * ca) + cia;
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), a));
- }
- }
+ comp_func_DestinationIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
result = s * dia
dest = s * dia * ca + d * cia
*/
-
-void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
- }
+ for (int i = 0; i < length; ++i)
+ Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::invAlpha(Ops::load(&dest[i]))));
} else {
- color = BYTE_MUL(color, const_alpha);
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, cia));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(color, 65535 - dest[i].alpha());
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::invAlpha(d)));
}
} else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- color = multiplyAlpha65535(color, ca);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(color, 65535 - d.alpha(), d, cia);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, cia));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceOut_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
- }
- } else {
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
- }
- }
+ comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(src[i], 65535 - dest[i].alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- QRgba64 s = multiplyAlpha65535(src[i], ca);
- dest[i] = interpolate65535(s, 65535 - d.alpha(), d, cia);
- }
- }
+ comp_func_SourceOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -534,56 +747,58 @@ void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = d * sia * ca + d * cia
= d * (sia * ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(~color);
- if (const_alpha != 255)
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], a);
+ auto sai = Ops::invAlpha(Ops::convert(color));
+ if (const_alpha != 255) {
+ sai = Ops::multiplyAlpha8bit(sai, const_alpha);
+ sai = Ops::add(sai, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
}
-}
-void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = 65535 - color.alpha();
- uint ca64k = const_alpha * 257;
- if (const_alpha != 255)
- a = qt_div_65535(a * ca64k) + 65535 - ca64k;
for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(dest[i], a);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sai));
}
}
-void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
+ auto sia = Ops::invAlpha(Ops::load(&src[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], sia);
+ auto sia = Ops::multiplyAlpha8bit(Ops::invAlpha(Ops::load(&src[i])), const_alpha);
+ sia = Ops::add(sia, cia);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationOut_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(dest[i], 65535 - src[i].alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- uint a = qt_div_65535((65535 - src[i].alpha()) * ca) + cia;
- dest[i] = multiplyAlpha65535(dest[i], a);
- }
- }
+ comp_func_DestinationOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -592,59 +807,57 @@ void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, c
= s*ca * da + d * (sia*ca + cia)
= s*ca * da + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha != 255) {
- color = BYTE_MUL(color, const_alpha);
- }
- uint sia = qAlpha(~color);
- for (int i = 0; i < length; ++i) {
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia);
- }
-}
-
-void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- uint sia = 65535 - color.alpha();
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto sia = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- dest[i] = interpolate65535(color, dest[i].alpha(), dest[i], sia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, sia));
}
}
-void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
}
} else {
for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceAtop_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha());
- }
- } else {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = multiplyAlpha255(src[i], const_alpha);
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha());
- }
- }
+ comp_func_SourceAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -652,69 +865,63 @@ void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = d*sa*ca + s*dia*ca + d *cia
= s*ca * dia + d * (sa*ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(color);
+ auto c = Ops::convert(color);
+ auto sa = Ops::alpha(c);
if (const_alpha != 255) {
- color = BYTE_MUL(color, const_alpha);
- a = qAlpha(color) + 255 - const_alpha;
- }
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
+ sa = Ops::add(Ops::alpha(c), cia);
}
-}
-void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = color.alpha();
- if (const_alpha != 255) {
- color = multiplyAlpha255(color, const_alpha);
- a = color.alpha() + 65535 - (const_alpha * 257);
- }
for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(d, a, color, 65535 - d.alpha());
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sa));
}
}
-void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::alpha(s)));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- uint a = qAlpha(s) + cia;
- dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ auto sa = Ops::add(Ops::alpha(s), cia);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, sa));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationAtop_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(d, s.alpha(), s, 65535 - d.alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- QRgba64 s = multiplyAlpha65535(src[i], ca);
- QRgba64 d = dest[i];
- uint a = s.alpha() + cia;
- dest[i] = interpolate65535(d, a, s, 65535 - d.alpha());
- }
- }
+ comp_func_DestinationAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -723,62 +930,58 @@ void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest,
= s*ca * dia + d * (sia*ca + cia)
= s*ca * dia + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_XOR_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- uint sia = qAlpha(~color);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto sia = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sia));
}
}
-void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- auto s = CONVERT(color);
- auto sia = CONST(65535 - color.alpha());
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, sia));
- }
-}
-
-void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_XOR_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = src[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
}
} else {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
}
}
}
+void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_XOR_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = LOAD(&src[i]);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, INVALPHA(s)));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, INVALPHA(s)));
- }
- }
+ comp_func_XOR_template<Rgba64Operations>(dest, src, length, const_alpha);
}
struct QFullCoverage {
@@ -827,84 +1030,67 @@ static inline uint mix_alpha_rgb64(uint da, uint sa)
Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca
*/
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage)
+template<class Ops>
+inline static void comp_func_solid_Plus_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint s = color;
-
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- d = comp_func_Plus_one_pixel(d, s);
- coverage.store(&dest[i], d);
+ auto c = Ops::convert(color);
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ auto d = Ops::load(&dest[i]);
+ d = Ops::plus(d, c);
+ Ops::store(&dest[i], d);
+ }
+ } else {
+ uint ia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ auto d = Ops::load(&dest[i]);
+ d = Ops::interpolate8bit(Ops::plus(d, c), const_alpha, d, ia);
+ Ops::store(&dest[i], d);
+ }
}
}
-void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Plus_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
- if (const_alpha == 255)
- comp_func_solid_Plus_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
-void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- auto b = CONVERT(color);
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- a = addWithSaturation(a, b);
- STORE(&dest[i], a);
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ d = Ops::plus(d, s);
+ Ops::store(&dest[i], d);
}
} else {
+ uint ia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto d = addWithSaturation(a, b);
- a = interpolate255(d, const_alpha, a, 255 - const_alpha);
- STORE(&dest[i], a);
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ d = Ops::interpolate8bit(Ops::plus(d, s), const_alpha, d, ia);
+ Ops::store(&dest[i], d);
}
}
}
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
{
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = src[i];
-
- d = comp_func_Plus_one_pixel(d, s);
+ comp_func_solid_Plus_template<Argb32Operations>(dest, length, color, const_alpha);
+}
- coverage.store(&dest[i], d);
- }
+void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255)
- comp_func_Plus_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha));
+ comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto b = LOAD(&src[i]);
- a = addWithSaturation(a, b);
- STORE(&dest[i], a);
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto b = LOAD(&src[i]);
- auto d = addWithSaturation(a, b);
- a = interpolate255(d, const_alpha, a, 255 - const_alpha);
- STORE(&dest[i], a);
- }
- }
+ comp_func_Plus_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*