summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@theqtcompany.com>2015-05-13 12:42:46 +0200
committerPaul Olav Tvete <paul.tvete@theqtcompany.com>2015-05-13 12:42:46 +0200
commit8524853227c753b5cfa14184a086ec0acff3930a (patch)
tree808fab49e65286a4b4416a8462bb78fc188dfeac /src/gui/painting
parentd5a6c1613b52ebc015aa85a46c1387909d435926 (diff)
parentbf06924f3ffd22747c93a720caa501d8478dcbe6 (diff)
Merge branch 'wip/highdpi' of git://code.qt.io/qt/qtbase into dev-highdpi
Conflicts: src/plugins/platforms/xcb/qxcbscreen.cpp src/plugins/platforms/xcb/qxcbwindow.cpp
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/painting.pri4
-rw-r--r--src/gui/painting/qblendfunctions.cpp2136
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp2197
-rw-r--r--src/gui/painting/qdrawhelper.cpp3349
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_p.h144
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp86
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h6
-rw-r--r--src/gui/painting/qimagescale.cpp1155
-rw-r--r--src/gui/painting/qimagescale_p.h9
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp247
-rw-r--r--src/gui/painting/qmatrix.cpp24
-rw-r--r--src/gui/painting/qmatrix.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp1
-rw-r--r--src/gui/painting/qpainter_p.h1
-rw-r--r--src/gui/painting/qpdf.cpp490
-rw-r--r--src/gui/painting/qpdf_p.h13
-rw-r--r--src/gui/painting/qrgba64.h16
-rw-r--r--src/gui/painting/qrgba64_p.h53
-rw-r--r--src/gui/painting/qtransform.cpp24
-rw-r--r--src/gui/painting/qtransform.h2
21 files changed, 4639 insertions, 5322 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index fafc67cf46..791b5f1a9a 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -60,6 +60,7 @@ SOURCES += \
painting/qbrush.cpp \
painting/qcolor.cpp \
painting/qcolor_p.cpp \
+ painting/qcompositionfunctions.cpp \
painting/qcosmeticstroker.cpp \
painting/qcssutil.cpp \
painting/qdrawhelper.cpp \
@@ -95,7 +96,8 @@ SOURCES += \
SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
-SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp
+SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
+ painting/qimagescale_sse4.cpp
AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
!ios {
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 478fe6564c..b3710411c9 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -432,10 +432,10 @@ static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
}
template<QtPixelOrder PixelOrder>
-void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+static void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb32_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
@@ -496,10 +496,10 @@ static void qt_blend_a2rgb30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
}
-void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+static void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb30_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
@@ -740,2071 +740,75 @@ void qt_transform_image_argb32_on_argb32(uchar *destPixels, int dbpl,
}
}
-SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGRs30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_scale_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_scale_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_scale_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_scale_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_scale_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_scale_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_scale_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- }
-};
-
+SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
+SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats];
+SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
-SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb16, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_blend_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_blend_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_blend_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+void qInitBlendFunctions()
+{
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_blend_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_blend_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_BGR30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- }
-};
-SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_transform_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb16;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_transform_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_transform_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+
+ qTransformFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_transform_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_transform_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qTransformFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_transform_image_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
-};
+}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
new file mode 100644
index 0000000000..ba428a7938
--- /dev/null
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -0,0 +1,2197 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#include <private/qdrawhelper_p.h>
+#include <private/qrgba64_p.h>
+
+QT_BEGIN_NAMESPACE
+
+# define PRELOAD_INIT(x)
+# define PRELOAD_INIT2(x,y)
+# define PRELOAD_COND(x)
+# define PRELOAD_COND2(x,y)
+
+/* The constant alpha factor describes an alpha factor that gets applied
+ to the result of the composition operation combining it with the destination.
+
+ The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1.
+ we get the unmodified operation
+
+ result = src op dest
+ dest = result * const_alpha + dest * (1. - const_alpha)
+
+ This means that in the comments below, the first line is the const_alpha==255 case, the
+ second line the general one.
+
+ In the lines below:
+ s == src, sa == alpha(src), sia = 1 - alpha(src)
+ d == dest, da == alpha(dest), dia = 1 - alpha(dest)
+ ca = const_alpha, cia = 1 - const_alpha
+
+ The methods exist in two variants. One where we have a constant source, the other
+ where the source is an array of pixels.
+*/
+
+/*
+ result = 0
+ d = d * cia
+*/
+#define comp_func_Clear_impl(dest, length, const_alpha)\
+{\
+ if (const_alpha == 255) {\
+ QT_MEMFILL_UINT(dest, length, 0);\
+ } else {\
+ int ialpha = 255 - const_alpha;\
+ PRELOAD_INIT(dest)\
+ for (int i = 0; i < length; ++i) {\
+ PRELOAD_COND(dest)\
+ dest[i] = BYTE_MUL(dest[i], ialpha);\
+ }\
+ }\
+}
+
+void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+{
+ comp_func_Clear_impl(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 {
+ int ialpha = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = multiplyAlpha255(dest[i], ialpha);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
+{
+ comp_func_Clear_impl(dest, length, const_alpha);
+}
+
+void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ qt_memfill64((quint64*)dest, 0, length);
+ else {
+ int ialpha = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = multiplyAlpha255(dest[i], ialpha);
+ }
+ }
+}
+
+/*
+ result = s
+ dest = s * ca + d * cia
+*/
+void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+{
+ if (const_alpha == 255) {
+ QT_MEMFILL_UINT(dest, length, color);
+ } else {
+ int ialpha = 255 - const_alpha;
+ color = BYTE_MUL(color, const_alpha);
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = color + BYTE_MUL(dest[i], ialpha);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ qt_memfill64((quint64*)dest, color, length);
+ else {
+ int ialpha = 255 - const_alpha;
+ color = multiplyAlpha255(color, const_alpha);
+ for (int i = 0; i < length; ++i) {
+ dest[i] = color + multiplyAlpha255(dest[i], ialpha);
+ }
+ }
+}
+
+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, length * sizeof(uint));
+ } else {
+ int ialpha = 255 - const_alpha;
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
+ }
+ }
+}
+
+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, length * sizeof(quint64));
+ else {
+ int ialpha = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = interpolate255(src[i], const_alpha, dest[i], ialpha);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
+{
+}
+
+void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
+{
+}
+
+void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
+{
+}
+
+void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint)
+{
+}
+
+/*
+ result = s + d * sia
+ dest = (s + d * sia) * ca + d * cia
+ = 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)
+{
+ if ((const_alpha & qAlpha(color)) == 255) {
+ QT_MEMFILL_UINT(dest, length, color);
+ } else {
+ if (const_alpha != 255)
+ color = BYTE_MUL(color, const_alpha);
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255 && color.isOpaque()) {
+ qt_memfill64((quint64*)dest, color, length);
+ } else {
+ if (const_alpha != 255)
+ color = multiplyAlpha255(color, const_alpha);
+ for (int i = 0; i < length; ++i) {
+ dest[i] = color + multiplyAlpha65535(dest[i], 65535 - color.alpha());
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ 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) {
+ PRELOAD_COND2(dest, src)
+ uint s = BYTE_MUL(src[i], const_alpha);
+ dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
+ }
+ }
+}
+
+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())
+ dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha());
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ QRgba64 s = multiplyAlpha255(src[i], const_alpha);
+ dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha());
+ }
+ }
+}
+
+/*
+ result = d + s * dia
+ 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);
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ 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)
+{
+ if (const_alpha != 255)
+ color = multiplyAlpha255(color, const_alpha);
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ dest[i] = d + multiplyAlpha65535(color, 65535 - d.alpha());
+ }
+}
+
+void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = BYTE_MUL(src[i], const_alpha);
+ dest[i] = d + BYTE_MUL(s, qAlpha(~d));
+ }
+ }
+}
+
+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) {
+ QRgba64 d = dest[i];
+ dest[i] = d + multiplyAlpha65535(src[i], 65535 - d.alpha());
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = multiplyAlpha255(src[i], const_alpha);
+ dest[i] = d + multiplyAlpha65535(s, 65535 - d.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)
+{
+ PRELOAD_INIT(dest)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
+ }
+ } else {
+ color = BYTE_MUL(color, const_alpha);
+ uint cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ dest[i] = multiplyAlpha65535(color, dest[i].alpha());
+ }
+ } else {
+ uint ca = const_alpha * 257;
+ uint cia = 65535 - ca;
+ color = multiplyAlpha65535(color, ca);
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ dest[i] = interpolate65535(color, d.alpha(), d, cia);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
+ }
+ } else {
+ uint cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = BYTE_MUL(src[i], const_alpha);
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
+ }
+ }
+}
+
+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) {
+ dest[i] = multiplyAlpha65535(src[i], 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, d.alpha(), d, cia);
+ }
+ }
+}
+
+/*
+ result = d * sa
+ 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)
+{
+ uint a = qAlpha(color);
+ if (const_alpha != 255) {
+ a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
+ }
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = BYTE_MUL(dest[i], a);
+ }
+}
+
+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) {
+ dest[i] = multiplyAlpha65535(dest[i], a);
+ }
+}
+
+void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
+ }
+ } else {
+ int cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
+ dest[i] = BYTE_MUL(dest[i], a);
+ }
+ }
+}
+
+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) {
+ dest[i] = multiplyAlpha65535(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;
+ dest[i] = multiplyAlpha65535(dest[i], a);
+ }
+ }
+}
+
+/*
+ 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)
+{
+ PRELOAD_INIT(dest)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
+ }
+ } else {
+ color = BYTE_MUL(color, const_alpha);
+ int cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ dest[i] = multiplyAlpha65535(color, 65535 - dest[i].alpha());
+ }
+ } else {
+ uint ca = const_alpha * 257;
+ uint cia = 65535 - ca;
+ color = multiplyAlpha65535(color, ca);
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ dest[i] = interpolate65535(color, 65535 - d.alpha(), d, cia);
+ }
+ }
+}
+
+void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
+ }
+ } else {
+ int cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint s = BYTE_MUL(src[i], const_alpha);
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
+ }
+ }
+}
+
+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);
+ }
+ }
+}
+
+/*
+ result = d * sia
+ 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)
+{
+ uint a = qAlpha(~color);
+ if (const_alpha != 255)
+ a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ dest[i] = BYTE_MUL(dest[i], a);
+ }
+}
+
+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);
+ }
+}
+
+void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
+ }
+ } else {
+ int cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
+ dest[i] = BYTE_MUL(dest[i], sia);
+ }
+ }
+}
+
+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);
+ }
+ }
+}
+
+/*
+ result = s*da + d*sia
+ dest = s*da*ca + d*sia*ca + d *cia
+ = 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);
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ 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)
+{
+ if (const_alpha != 255)
+ color = multiplyAlpha255(color, const_alpha);
+ uint sia = 65535 - color.alpha();
+ for (int i = 0; i < length; ++i) {
+ dest[i] = interpolate65535(color, dest[i].alpha(), dest[i], sia);
+ }
+}
+
+void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint s = src[i];
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint s = BYTE_MUL(src[i], const_alpha);
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ }
+ }
+}
+
+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());
+ }
+ }
+}
+
+/*
+ result = d*sa + s*dia
+ 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)
+{
+ uint a = qAlpha(color);
+ if (const_alpha != 255) {
+ color = BYTE_MUL(color, const_alpha);
+ a = qAlpha(color) + 255 - const_alpha;
+ }
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
+ }
+}
+
+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());
+ }
+}
+
+void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint s = src[i];
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
+ }
+ } else {
+ int cia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ 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));
+ }
+ }
+}
+
+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 {
+ int ca = const_alpha * 257;
+ int 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());
+ }
+ }
+}
+
+/*
+ result = d*sia + s*dia
+ dest = d*sia*ca + s*dia*ca + d *cia
+ = 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)
+{
+ if (const_alpha != 255)
+ color = BYTE_MUL(color, const_alpha);
+ uint sia = qAlpha(~color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~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);
+ uint sia = 65535 - color.alpha();
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ dest[i] = interpolate65535(color, 65535 - d.alpha(), d, sia);
+ }
+}
+
+void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ PRELOAD_INIT2(dest, src)
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = BYTE_MUL(src[i], const_alpha);
+ dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ }
+ }
+}
+
+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) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+ dest[i] = interpolate65535(s, 65535 - d.alpha(), d, 65535 - s.alpha());
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = multiplyAlpha255(src[i], const_alpha);
+ dest[i] = interpolate65535(s, 65535 - d.alpha(), d, 65535 - s.alpha());
+ }
+ }
+}
+
+struct QFullCoverage {
+ inline void store(uint *dest, const uint src) const
+ {
+ *dest = src;
+ }
+};
+
+struct QPartialCoverage {
+ inline QPartialCoverage(uint const_alpha)
+ : ca(const_alpha)
+ , ica(255 - const_alpha)
+ {
+ }
+
+ inline void store(uint *dest, const uint src) const
+ {
+ *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica);
+ }
+
+private:
+ const uint ca;
+ const uint ica;
+};
+
+static inline int mix_alpha(int da, int sa)
+{
+ return 255 - ((255 - sa) * (255 - da) >> 8);
+}
+
+/*
+ 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)
+{
+ uint s = color;
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ d = comp_func_Plus_one_pixel(d, s);
+ coverage.store(&dest[i], d);
+ }
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl_rgb64(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ QRgba64 s = color;
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ d = comp_func_Plus_one_pixel(d, s);
+ coverage.store(&dest[i], d);
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, 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)
+{
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ dest[i] = addWithSaturation(dest[i], color);
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = addWithSaturation(dest[i], color);
+ dest[i] = interpolate255(d, const_alpha, dest[i], 255 - const_alpha);
+ }
+ }
+}
+
+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)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ d = comp_func_Plus_one_pixel(d, s);
+
+ coverage.store(&dest[i], d);
+ }
+}
+
+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));
+}
+
+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) {
+ dest[i] = addWithSaturation(dest[i], src[i]);
+ }
+ } else {
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = addWithSaturation(dest[i], src[i]);
+ dest[i] = interpolate255(d, const_alpha, dest[i], 255 - const_alpha);
+ }
+ }
+}
+
+/*
+ Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline int multiply_op(int dst, int src, int da, int sa)
+{
+ return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) multiply_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) multiply_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ = Sca + Dca - Sca.Dca
+*/
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Screen(uint *dest, const uint *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));
+}
+
+/*
+ if 2.Dca < Da
+ Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise
+ Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline int overlay_op(int dst, int src, int da, int sa)
+{
+ const int temp = src * (255 - da) + dst * (255 - sa);
+ if (2 * dst < da)
+ return qt_div_255(2 * src * dst + temp);
+ else
+ return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) overlay_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) overlay_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ Da' = Sa + Da - Sa.Da
+*/
+static inline int darken_op(int dst, int src, int da, int sa)
+{
+ return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) darken_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) darken_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ Da' = Sa + Da - Sa.Da
+*/
+static inline int lighten_op(int dst, int src, int da, int sa)
+{
+ return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) lighten_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) lighten_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ if Sca.Da + Dca.Sa >= Sa.Da
+ Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise
+ Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline int color_dodge_op(int dst, int src, int da, int sa)
+{
+ const int sa_da = sa * da;
+ const int dst_sa = dst * sa;
+ const int src_da = src * da;
+
+ const int temp = src * (255 - da) + dst * (255 - sa);
+ if (src_da + dst_sa >= sa_da)
+ return qt_div_255(sa_da + temp);
+ else
+ return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp);
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a,b) color_dodge_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) color_dodge_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ if Sca.Da + Dca.Sa <= Sa.Da
+ Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise
+ Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline int color_burn_op(int dst, int src, int da, int sa)
+{
+ const int src_da = src * da;
+ const int dst_sa = dst * sa;
+ const int sa_da = sa * da;
+
+ const int temp = src * (255 - da) + dst * (255 - sa);
+
+ if (src == 0 || src_da + dst_sa <= sa_da)
+ return qt_div_255(temp);
+ return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp);
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) color_burn_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) color_burn_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ if 2.Sca < Sa
+ Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise
+ Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline uint hardlight_op(int dst, int src, int da, int sa)
+{
+ const uint temp = src * (255 - da) + dst * (255 - sa);
+
+ if (2 * src < sa)
+ return qt_div_255(2 * src * dst + temp);
+ else
+ return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) hardlight_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) hardlight_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ if 2.Sca <= Sa
+ Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise if 2.Sca > Sa and 4.Dca <= Da
+ Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
+ otherwise if 2.Sca > Sa and 4.Dca > Da
+ Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+static inline int soft_light_op(int dst, int src, int da, int sa)
+{
+ const int src2 = src << 1;
+ const int dst_np = da != 0 ? (255 * dst) / da : 0;
+ const int temp = (src * (255 - da) + dst * (255 - sa)) * 255;
+
+ if (src2 < sa)
+ return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025;
+ else if (4 * dst <= da)
+ return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
+ else {
+ return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
+ }
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) soft_light_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) soft_light_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
+ = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
+*/
+static inline int difference_op(int dst, int src, int da, int sa)
+{
+ return src + dst - qt_div_255(2 * qMin(src * da, dst * sa));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) difference_op(a, b, da, sa)
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) difference_op(a, b, da, sa)
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+/*
+ Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+*/
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
+{
+ int sa = qAlpha(color);
+ int sr = qRed(color);
+ int sg = qGreen(color);
+ int sb = qBlue(color);
+
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
+ uint d = dest[i];
+ int da = qAlpha(d);
+
+#define OP(a, b) (a + b - qt_div_255(2*(a*b)))
+ int r = OP( qRed(d), sr);
+ int b = OP( qBlue(d), sb);
+ int g = OP(qGreen(d), sg);
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint 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));
+}
+
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
+ uint d = dest[i];
+ uint s = src[i];
+
+ int da = qAlpha(d);
+ int sa = qAlpha(s);
+
+#define OP(a, b) (a + b - ((a*b) >> 7))
+ int r = OP( qRed(d), qRed(s));
+ int b = OP( qBlue(d), qBlue(s));
+ int g = OP(qGreen(d), qGreen(s));
+ int a = mix_alpha(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba(r, g, b, a));
+ }
+}
+
+void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *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));
+}
+
+void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--)
+ *dest++ |= color;
+}
+
+void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--)
+ *dest++ |= *src++;
+}
+
+void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color |= 0xff000000;
+ while (length--)
+ *dest++ &= color;
+}
+
+void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (*src & *dest) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color &= 0x00ffffff;
+ while (length--)
+ *dest++ ^= color;
+}
+
+void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (*src ^ *dest) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color = ~color;
+ while (length--) {
+ *dest = (color & ~(*dest)) | 0xff000000;
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (~(*src) & ~(*dest)) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color = ~color | 0xff000000;
+ while (length--) {
+ *dest = color | ~(*dest);
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = ~(*src) | ~(*dest) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color = ~color & 0x00ffffff;
+ while (length--) {
+ *dest = color ^ (*dest);
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = ((~(*src)) ^ (*dest)) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
+ uint color, uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ qt_memfill(dest, ~color | 0xff000000, length);
+}
+
+void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--)
+ *dest++ = ~(*src++) | 0xff000000;
+}
+
+void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color = ~color | 0xff000000;
+ while (length--) {
+ *dest = color & *dest;
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (~(*src) & *dest) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (color & ~(*dest)) | 0xff000000;
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (*src & ~(*dest)) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (~(*src) | *dest) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ color = ~color | 0xff000000;
+ while (length--)
+ *dest++ |= color;
+}
+
+void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (*src | ~(*dest)) | 0xff000000;
+ ++dest; ++src;
+ }
+}
+
+void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(const_alpha);
+ while (length--) {
+ *dest = (color | ~(*dest)) | 0xff000000;
+ ++dest;
+ }
+}
+
+void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(src);
+ comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha);
+}
+
+void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(color);
+ comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha);
+}
+
+void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(src);
+ comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha);
+}
+
+void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(color);
+ comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha);
+}
+
+void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest,
+ const uint *Q_DECL_RESTRICT src,
+ int length,
+ uint const_alpha)
+{
+ Q_UNUSED(src);
+ rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha);
+}
+
+void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest,
+ int length,
+ uint color,
+ uint const_alpha)
+{
+ Q_UNUSED(color);
+ rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha);
+}
+
+CompositionFunctionSolid qt_functionForModeSolid_C[] = {
+ comp_func_solid_SourceOver,
+ comp_func_solid_DestinationOver,
+ comp_func_solid_Clear,
+ comp_func_solid_Source,
+ comp_func_solid_Destination,
+ comp_func_solid_SourceIn,
+ comp_func_solid_DestinationIn,
+ comp_func_solid_SourceOut,
+ comp_func_solid_DestinationOut,
+ comp_func_solid_SourceAtop,
+ comp_func_solid_DestinationAtop,
+ comp_func_solid_XOR,
+ comp_func_solid_Plus,
+ comp_func_solid_Multiply,
+ comp_func_solid_Screen,
+ comp_func_solid_Overlay,
+ comp_func_solid_Darken,
+ comp_func_solid_Lighten,
+ comp_func_solid_ColorDodge,
+ comp_func_solid_ColorBurn,
+ comp_func_solid_HardLight,
+ comp_func_solid_SoftLight,
+ comp_func_solid_Difference,
+ comp_func_solid_Exclusion,
+ rasterop_solid_SourceOrDestination,
+ rasterop_solid_SourceAndDestination,
+ rasterop_solid_SourceXorDestination,
+ rasterop_solid_NotSourceAndNotDestination,
+ rasterop_solid_NotSourceOrNotDestination,
+ rasterop_solid_NotSourceXorDestination,
+ rasterop_solid_NotSource,
+ rasterop_solid_NotSourceAndDestination,
+ rasterop_solid_SourceAndNotDestination,
+ rasterop_solid_NotSourceOrDestination,
+ rasterop_solid_SourceOrNotDestination,
+ rasterop_solid_ClearDestination,
+ rasterop_solid_SetDestination,
+ rasterop_solid_NotDestination
+};
+
+CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
+ comp_func_solid_SourceOver_rgb64,
+ comp_func_solid_DestinationOver_rgb64,
+ comp_func_solid_Clear_rgb64,
+ comp_func_solid_Source_rgb64,
+ comp_func_solid_Destination_rgb64,
+ comp_func_solid_SourceIn_rgb64,
+ comp_func_solid_DestinationIn_rgb64,
+ comp_func_solid_SourceOut_rgb64,
+ comp_func_solid_DestinationOut_rgb64,
+ comp_func_solid_SourceAtop_rgb64,
+ comp_func_solid_DestinationAtop_rgb64,
+ comp_func_solid_XOR_rgb64,
+ comp_func_solid_Plus_rgb64,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+CompositionFunction qt_functionForMode_C[] = {
+ comp_func_SourceOver,
+ comp_func_DestinationOver,
+ comp_func_Clear,
+ comp_func_Source,
+ comp_func_Destination,
+ comp_func_SourceIn,
+ comp_func_DestinationIn,
+ comp_func_SourceOut,
+ comp_func_DestinationOut,
+ comp_func_SourceAtop,
+ comp_func_DestinationAtop,
+ comp_func_XOR,
+ comp_func_Plus,
+ comp_func_Multiply,
+ comp_func_Screen,
+ comp_func_Overlay,
+ comp_func_Darken,
+ comp_func_Lighten,
+ comp_func_ColorDodge,
+ comp_func_ColorBurn,
+ comp_func_HardLight,
+ comp_func_SoftLight,
+ comp_func_Difference,
+ comp_func_Exclusion,
+ rasterop_SourceOrDestination,
+ rasterop_SourceAndDestination,
+ rasterop_SourceXorDestination,
+ rasterop_NotSourceAndNotDestination,
+ rasterop_NotSourceOrNotDestination,
+ rasterop_NotSourceXorDestination,
+ rasterop_NotSource,
+ rasterop_NotSourceAndDestination,
+ rasterop_SourceAndNotDestination,
+ rasterop_NotSourceOrDestination,
+ rasterop_SourceOrNotDestination,
+ rasterop_ClearDestination,
+ rasterop_SetDestination,
+ rasterop_NotDestination
+};
+
+CompositionFunction64 qt_functionForMode64_C[] = {
+ comp_func_SourceOver_rgb64,
+ comp_func_DestinationOver_rgb64,
+ comp_func_Clear_rgb64,
+ comp_func_Source_rgb64,
+ comp_func_Destination_rgb64,
+ comp_func_SourceIn_rgb64,
+ comp_func_DestinationIn_rgb64,
+ comp_func_SourceOut_rgb64,
+ comp_func_DestinationOut_rgb64,
+ comp_func_SourceAtop_rgb64,
+ comp_func_DestinationAtop_rgb64,
+ comp_func_XOR_rgb64,
+ comp_func_Plus_rgb64,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index b6f06135cd..e46e997f1d 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -185,6 +185,36 @@ static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int
}
template<QImage::Format Format>
+static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+
+ Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+
+ Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
+ Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
+ Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+
+ for (int i = 0; i < count; ++i) {
+ uint red = (src[i] >> redShift<Format>()) & redMask;
+ uint green = (src[i] >> greenShift<Format>()) & greenMask;
+ uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+
+ red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
+ green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
+ blue = (blue << blueLeftShift) | (blue >> blueRightShift);
+ buffer[i] = QRgba64::fromRgba(red, green, blue, 255);
+ }
+
+ return buffer;
+}
+
+template<QImage::Format Format>
static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
{
@@ -220,6 +250,41 @@ static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint
}
template<QImage::Format Format>
+static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+
+ Q_CONSTEXPR uchar alphaLeftShift = 8 - alphaWidth<Format>();
+ Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+
+ Q_CONSTEXPR uchar alphaRightShift = 2 * alphaWidth<Format>() - 8;
+ Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
+ Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
+ Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+
+ for (int i = 0; i < count; ++i) {
+ uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
+ uint red = (src[i] >> redShift<Format>()) & redMask;
+ uint green = (src[i] >> greenShift<Format>()) & greenMask;
+ uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+
+ alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
+ red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
+ green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
+ blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
+ buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
+ }
+
+ return buffer;
+}
+
+template<QImage::Format Format>
static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
{
@@ -321,7 +386,8 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe
false, bitsPerPixel<Format>(),
convertToRGB32<Format>,
convertRGBFromARGB32PM<Format>,
- convertRGBFromRGB32<Format>
+ convertRGBFromRGB32<Format>,
+ convertToRGB64<Format>
};
}
@@ -335,7 +401,8 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe
true, bitsPerPixel<Format>(),
convertARGBPMToARGB32PM<Format>,
convertARGBPMFromARGB32PM<Format>,
- convertARGBPMFromRGB32<Format>
+ convertARGBPMFromRGB32<Format>,
+ convertARGBPMToARGB64PM<Format>
};
}
@@ -350,6 +417,14 @@ static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint
return buffer;
}
+static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *clut)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(clut[src[i]]).premultiplied();
+ return buffer;
+}
+
static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int,
const QPixelLayout *, const QRgb *)
{
@@ -392,6 +467,22 @@ static const uint *QT_FASTCALL convertGrayscale8ToRGB32(uint *buffer, const uint
return buffer;
}
+static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba(0, 0, 0, src[i]);
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba(src[i], src[i], src[i], 255);
+ return buffer;
+}
+
static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
{
@@ -408,6 +499,111 @@ static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const
return buffer;
}
+#ifdef __SSE2__
+template<bool RGBA, bool maskAlpha>
+static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+{
+ const __m128i amask = _mm_set1_epi32(0xff000000);
+ int i = 0;
+ if (((uintptr_t)buffer & 0xf) && count > 0) {
+ uint s = *src++;
+ if (RGBA)
+ s = RGBA2ARGB(s);
+ *buffer++ = QRgba64::fromArgb32(s);
+ i++;
+ }
+ for (; i < count-3; i += 4) {
+ __m128i vs = _mm_loadu_si128((const __m128i*)src);
+ if (maskAlpha)
+ vs = _mm_or_si128(vs, amask);
+ src += 4;
+ __m128i v1 = _mm_unpacklo_epi8(vs, vs);
+ __m128i v2 = _mm_unpackhi_epi8(vs, vs);
+ if (!RGBA) {
+ v1 = _mm_shufflelo_epi16(v1, _MM_SHUFFLE(3, 0, 1, 2));
+ v2 = _mm_shufflelo_epi16(v2, _MM_SHUFFLE(3, 0, 1, 2));
+ v1 = _mm_shufflehi_epi16(v1, _MM_SHUFFLE(3, 0, 1, 2));
+ v2 = _mm_shufflehi_epi16(v2, _MM_SHUFFLE(3, 0, 1, 2));
+ }
+ _mm_store_si128((__m128i*)(buffer), v1);
+ buffer += 2;
+ _mm_store_si128((__m128i*)(buffer), v2);
+ buffer += 2;
+ }
+
+ for (; i < count; ++i) {
+ uint s = *src++;
+ if (RGBA)
+ s = RGBA2ARGB(s);
+ *buffer++ = QRgba64::fromArgb32(s);
+ }
+}
+#endif
+
+static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertARGB32PMToARGB64PM_sse2<false, true>(buffer, src, count);
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(0xff000000 | src[i]);
+#endif
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+ for (int i = 0; i < count; ++i)
+ buffer[i] = buffer[i].premultiplied();
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied();
+#endif
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(src[i]);
+#endif
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+ for (int i = 0; i < count; ++i)
+ buffer[i] = buffer[i].premultiplied();
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])).premultiplied();
+#endif
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i]));
+#endif
+ return buffer;
+}
+
static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
{
@@ -441,6 +637,60 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui
return buffer;
}
+#ifdef __SSE2__
+template<QtPixelOrder PixelOrder>
+static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+{
+ const __m128i rmask = _mm_set1_epi32(0x3ff00000);
+ const __m128i gmask = _mm_set1_epi32(0x000ffc00);
+ const __m128i bmask = _mm_set1_epi32(0x000003ff);
+ const __m128i afactor = _mm_set1_epi16(0x5555);
+ int i = 0;
+ if (((uintptr_t)buffer & 0xf) && count > 0) {
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+ i++;
+ }
+ for (; i < count-3; i += 4) {
+ __m128i vs = _mm_loadu_si128((const __m128i*)src);
+ src += 4;
+ __m128i va = _mm_srli_epi32(vs, 30);
+ __m128i vr = _mm_and_si128(vs, rmask);
+ __m128i vb = _mm_and_si128(vs, bmask);
+ __m128i vg = _mm_and_si128(vs, gmask);
+ va = _mm_mullo_epi16(va, afactor);
+ vr = _mm_or_si128(_mm_srli_epi32(vr, 14), _mm_srli_epi32(vr, 24));
+ vg = _mm_or_si128(_mm_srli_epi32(vg, 4), _mm_srli_epi32(vg, 14));
+ vb = _mm_or_si128(_mm_slli_epi32(vb, 6), _mm_srli_epi32(vb, 4));
+ __m128i vrb;
+ if (PixelOrder == PixelOrderRGB)
+ vrb = _mm_or_si128(vr, _mm_slli_si128(vb, 2));
+ else
+ vrb = _mm_or_si128(vb, _mm_slli_si128(vr, 2));
+ __m128i vga = _mm_or_si128(vg, _mm_slli_si128(va, 2));
+ _mm_store_si128((__m128i*)(buffer), _mm_unpacklo_epi16(vrb, vga));
+ buffer += 2;
+ _mm_store_si128((__m128i*)(buffer), _mm_unpackhi_epi16(vrb, vga));
+ buffer += 2;
+ }
+
+ for (; i < count; ++i)
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+}
+#endif
+
+template<QtPixelOrder PixelOrder>
+static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *, const QRgb *)
+{
+#ifdef __SSE2__
+ qConvertA2RGB30PMToARGB64PM_sse2<PixelOrder>(buffer, src, count);
+#else
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
+#endif
+ return buffer;
+}
+
template<QtPixelOrder PixelOrder>
static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count,
const QPixelLayout *, const QRgb *)
@@ -602,15 +852,15 @@ inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint
// convertFromArgb32() assumes that no color channel is more than 8 bits.
// QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits.
QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0 }, // Format_Invalid
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0 }, // Format_Mono
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0 }, // Format_MonoLSB
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0 }, // Format_Indexed8
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0, 0 }, // Format_Invalid
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Mono
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_MonoLSB
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Indexed8
// Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
// but everywhere this generic conversion would be wrong is currently overloaded.
- { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough }, // Format_RGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough }, // Format_ARGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough }, // Format_ARGB32_Premultiplied
+ { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32
+ { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32
+ { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied
#ifdef Q_COMPILER_CONSTEXPR
pixelLayoutRGB<QImage::Format_RGB16>(),
pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(),
@@ -625,55 +875,73 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16,
convertToRGB32<QImage::Format_RGB16>,
convertRGBFromARGB32PM<QImage::Format_RGB16>,
- convertRGBFromRGB32<QImage::Format_RGB16>},
+ convertRGBFromRGB32<QImage::Format_RGB16>,
+ convertToRGB64<QImage::Format_RGB16>,
+ },
{ 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24,
convertARGBPMToARGB32PM<QImage::Format_ARGB8565_Premultiplied>,
convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied>,
- convertARGBPMFromRGB32<QImage::Format_ARGB8565_Premultiplied>},
+ convertARGBPMFromRGB32<QImage::Format_ARGB8565_Premultiplied>,
+ convertARGBPMToARGB64PM<QImage::Format_ARGB8565_Premultiplied>,
+ },
{ 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24,
convertToRGB32<QImage::Format_RGB666>,
convertRGBFromARGB32PM<QImage::Format_RGB666>,
- convertRGBFromRGB32<QImage::Format_RGB666>},
+ convertRGBFromRGB32<QImage::Format_RGB666>,
+ convertToRGB64<QImage::Format_RGB666>,
+ },
{ 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24,
convertARGBPMToARGB32PM<QImage::Format_ARGB6666_Premultiplied>,
convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied>,
- convertARGBPMFromRGB32<QImage::Format_ARGB6666_Premultiplied>},
+ convertARGBPMFromRGB32<QImage::Format_ARGB6666_Premultiplied>,
+ convertARGBPMToARGB64PM<QImage::Format_ARGB6666_Premultiplied>,
+ },
{ 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16,
convertToRGB32<QImage::Format_RGB555>,
convertRGBFromARGB32PM<QImage::Format_RGB555>,
- convertRGBFromRGB32<QImage::Format_RGB555> },
+ convertRGBFromRGB32<QImage::Format_RGB555>,
+ convertToRGB64<QImage::Format_RGB555>,
+ },
{ 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24,
convertARGBPMToARGB32PM<QImage::Format_ARGB8555_Premultiplied>,
convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied>,
- convertARGBPMFromRGB32<QImage::Format_ARGB8555_Premultiplied>},
+ convertARGBPMFromRGB32<QImage::Format_ARGB8555_Premultiplied>,
+ convertARGBPMToARGB64PM<QImage::Format_ARGB8555_Premultiplied>,
+ },
{ 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24,
convertToRGB32<QImage::Format_RGB888>,
convertRGBFromARGB32PM<QImage::Format_RGB888>,
- convertRGBFromRGB32<QImage::Format_RGB888>},
+ convertRGBFromRGB32<QImage::Format_RGB888>,
+ convertToRGB64<QImage::Format_RGB888>,
+ },
{ 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16,
convertToRGB32<QImage::Format_RGB444>,
convertRGBFromARGB32PM<QImage::Format_RGB444>,
- convertRGBFromRGB32<QImage::Format_RGB444>},
+ convertRGBFromRGB32<QImage::Format_RGB444>,
+ convertToRGB64<QImage::Format_RGB444>,
+ },
{ 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16,
convertARGBPMToARGB32PM<QImage::Format_ARGB4444_Premultiplied>,
convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied>,
- convertARGBPMFromRGB32<QImage::Format_ARGB4444_Premultiplied>},
+ convertARGBPMFromRGB32<QImage::Format_ARGB4444_Premultiplied>,
+ convertARGBPMToARGB64PM<QImage::Format_ARGB4444_Premultiplied>,
+ },
#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888
- { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888
- { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32}, // Format_RGBA8888_Premultiplied
+ { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
+ { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888
+ { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM}, // Format_RGBA8888_Premultiplied
#else
- { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888
- { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888 (ABGR32)
- { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBA8888_Premultiplied
+ { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
+ { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32)
+ { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBA8888_Premultiplied
#endif
- { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR> }, // Format_BGR30
- { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied
- { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB> }, // Format_RGB30
- { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied
- { 0, 0, 0, 0, 0, 0, 8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0 }, // Format_Alpha8
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32 } // Format_Grayscale8
+ { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30
+ { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied
+ { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30
+ { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied
+ { 0, 0, 0, 0, 0, 0, 8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8
+ { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8
};
FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
@@ -764,29 +1032,14 @@ static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBu
const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
uint buffer32[buffer_size];
const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length);
- ptr = const_cast<uint *>(layout->convertToARGB32PM(buffer32, ptr, length, layout, 0));
-
- for (int i = 0; i < length; ++i) {
- buffer[i] = QRgba64::fromArgb32(ptr[i]);
- }
- return buffer;
-}
-
-static QRgba64 *QT_FASTCALL destFetch64ARGB32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
-{
- const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
- for (int i = 0; i < length; ++i)
- buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied();
- return buffer;
+ return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, layout, 0));
}
-template<QtPixelOrder PixelOrder>
-static QRgba64 *QT_FASTCALL destFetch64RGB30(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+static QRgba64 *QT_FASTCALL destFetch64uint32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
{
+ const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
- for (int i = 0; i < length; ++i)
- buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
- return buffer;
+ return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, src, length, layout, 0));
}
static DestFetchProc destFetchProc[QImage::NImageFormats] =
@@ -824,9 +1077,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetch64, // Format_Mono,
destFetch64, // Format_MonoLSB
0, // Format_Indexed8
- destFetch64, // Format_RGB32
- destFetch64ARGB32, // Format_ARGB32,
- destFetch64, // Format_ARGB32_Premultiplied
+ destFetch64uint32, // Format_RGB32
+ destFetch64uint32, // Format_ARGB32,
+ destFetch64uint32, // Format_ARGB32_Premultiplied
destFetch64, // Format_RGB16
destFetch64, // Format_ARGB8565_Premultiplied
destFetch64, // Format_RGB666
@@ -836,13 +1089,13 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetch64, // Format_RGB888
destFetch64, // Format_RGB444
destFetch64, // Format_ARGB4444_Premultiplied
- destFetch64, // Format_RGBX8888
- destFetch64, // Format_RGBA8888
- destFetch64, // Format_RGBA8888_Premultiplied
- destFetch64RGB30<PixelOrderBGR>, // Format_BGR30
- destFetch64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied
- destFetch64RGB30<PixelOrderRGB>, // Format_RGB30
- destFetch64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied
+ destFetch64uint32, // Format_RGBX8888
+ destFetch64uint32, // Format_RGBA8888
+ destFetch64uint32, // Format_RGBA8888_Premultiplied
+ destFetch64uint32, // Format_BGR30
+ destFetch64uint32, // Format_A2BGR30_Premultiplied
+ destFetch64uint32, // Format_RGB30
+ destFetch64uint32, // Format_A2RGB30_Premultiplied
destFetch64, // Format_Alpha8
destFetch64, // Format_Grayscale8
};
@@ -991,6 +1244,40 @@ static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, c
}
}
+#ifdef __SSE2__
+template<QtPixelOrder PixelOrder>
+static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *buffer, int count)
+{
+ const __m128i gmask = _mm_set1_epi32(0x000ffc00);
+ const __m128i cmask = _mm_set1_epi32(0x000003ff);
+ int i = 0;
+ __m128i vr, vg, vb, va;
+ for (; i < count-1; i += 2) {
+ __m128i vs = _mm_loadu_si128((const __m128i*)buffer);
+ buffer += 2;
+ vr = _mm_srli_epi64(vs, 6);
+ vg = _mm_srli_epi64(vs, 16 + 6 - 10);
+ vb = _mm_srli_epi64(vs, 32 + 6);
+ vr = _mm_and_si128(vr, cmask);
+ vg = _mm_and_si128(vg, gmask);
+ vb = _mm_and_si128(vb, cmask);
+ va = _mm_srli_epi64(vs, 48 + 14);
+ if (PixelOrder == PixelOrderRGB)
+ vr = _mm_slli_epi32(vr, 20);
+ else
+ vb = _mm_slli_epi32(vb, 20);
+ va = _mm_slli_epi32(va, 30);
+ __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va));
+ vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0));
+ _mm_storel_epi64((__m128i*)dest, vd);
+ dest += 2;
+ }
+
+ for (; i < count; ++i)
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+}
+#endif
+
static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
@@ -999,13 +1286,25 @@ static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, in
}
}
+static void QT_FASTCALL destStore64RGBA8888(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = ARGB2RGBA(buffer[i].unpremultiplied().toArgb32());
+ }
+}
+
template<QtPixelOrder PixelOrder>
static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
+#ifdef __SSE2__
+ qConvertARGB64PMToA2RGB30PM_sse2<PixelOrder>(dest, buffer, length);
+#else
for (int i = 0; i < length; ++i) {
dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]);
}
+#endif
}
static DestStoreProc destStoreProc[QImage::NImageFormats] =
@@ -1056,7 +1355,7 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_RGB444
destStore64, // Format_ARGB4444_Premultiplied
destStore64, // Format_RGBX8888
- destStore64, // Format_RGBA8888
+ destStore64RGBA8888, // Format_RGBA8888
destStore64, // Format_RGBA8888_Premultiplied
destStore64RGB30<PixelOrderBGR>, // Format_BGR30
destStore64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied
@@ -1121,6 +1420,21 @@ static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Opera
return buffer;
}
+static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Operator *,
+ const QSpanData *data, int y, int x, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
+ if (layout->bpp != QPixelLayout::BPP32) {
+ uint buffer32[buffer_size];
+ const uint *ptr = qFetchPixels[layout->bpp](buffer32, data->texture.scanLine(y), x, length);
+ return layout->convertToARGB64PM(buffer, ptr, length, layout, clut);
+ } else {
+ const uint *src = (const uint *)data->texture.scanLine(y) + x;
+ return layout->convertToARGB64PM(buffer, src, length, layout, clut);
+ }
+}
+
// blendType is either BlendTransformed or BlendTransformedTiled
template<TextureBlendType blendType>
static const uint *QT_FASTCALL fetchTransformedARGB32PM(uint *buffer, const Operator *, const QSpanData *data,
@@ -1288,6 +1602,111 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
return layout->convertToARGB32PM(buffer, buffer, length, layout, clut);
}
+template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
+static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
+{
+ int image_width = data->texture.width;
+ int image_height = data->texture.height;
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ FetchPixelFunc fetch = qFetchPixel[layout->bpp];
+ const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
+
+ uint buffer32[buffer_size];
+ QRgba64 *b = buffer;
+ if (data->fast_matrix) {
+ // The increment pr x in the scanline
+ int fdx = (int)(data->m11 * fixed_scale);
+ int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy
+ + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy
+ + data->m12 * cx + data->dy) * fixed_scale);
+
+ int i = 0, j = 0;
+ while (i < length) {
+ if (j == buffer_size) {
+ layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut);
+ b += buffer_size;
+ j = 0;
+ }
+ int px = fx >> 16;
+ int py = fy >> 16;
+
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
+ } else {
+ px = qBound(0, px, image_width - 1);
+ py = qBound(0, py, image_height - 1);
+ }
+ buffer32[j] = fetch(data->texture.scanLine(py), px);
+
+ fx += fdx;
+ fy += fdy;
+ ++i; ++j;
+ }
+ if (j > 0) {
+ layout->convertToARGB64PM(b, buffer32, j, layout, clut);
+ b += j;
+ }
+ } else {
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+
+ int i = 0, j = 0;
+ while (i < length) {
+ if (j == buffer_size) {
+ layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut);
+ b += buffer_size;
+ j = 0;
+ }
+ const qreal iw = fw == 0 ? 1 : 1 / fw;
+ const qreal tx = fx * iw;
+ const qreal ty = fy * iw;
+ int px = int(tx) - (tx < 0);
+ int py = int(ty) - (ty < 0);
+
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
+ } else {
+ px = qBound(0, px, image_width - 1);
+ py = qBound(0, py, image_height - 1);
+ }
+ buffer32[j] = fetch(data->texture.scanLine(py), px);
+
+ fx += fdx;
+ fy += fdy;
+ fw += fdw;
+ //force increment to avoid /0
+ if (!fw) {
+ fw += fdw;
+ }
+ ++i; ++j;
+ }
+ if (j > 0) {
+ layout->convertToARGB64PM(b, buffer32, j, layout, clut);
+ b += j;
+ }
+ }
+ return buffer;
+}
+
/** \internal
interpolate 4 argb pixels with the distx and disty factor.
distx and disty bust be between 0 and 16
@@ -1379,43 +1798,41 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i
#endif
#if defined(__SSE2__)
-static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
-{
- // First interpolate right and left pixels in parallel.
- __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl));
- __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br));
- vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128());
- vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128());
- vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx));
- vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx));
- __m128i vtb = _mm_add_epi16(vl, vr);
- vtb = _mm_srli_epi16(vtb, 8);
- // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop)
-
- // Now the last interpolate between top and bottom interpolations.
- const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0));
- const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0));
- const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty);
- vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8));
- // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb }
- vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add.
- vtb = _mm_srli_epi32(vtb, 8);
- vtb = _mm_packs_epi32(vtb, _mm_setzero_si128());
- vtb = _mm_packus_epi16(vtb, _mm_setzero_si128());
- return _mm_cvtsi128_si32(vtb);
+static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
+{
+ const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
+
+ __m128i vt = _mm_loadu_si128((const __m128i*)t);
+ if (disty) {
+ __m128i vb = _mm_loadu_si128((const __m128i*)b);
+ vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty));
+ vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty));
+ vt = _mm_add_epi16(vt, vb);
+ }
+ vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
+ vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
+#ifdef Q_PROCESSOR_X86_64
+ return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt));
+#else
+ QRgba64 out;
+ _mm_storel_epi64((__m128i*)&out, vt);
+ return out;
+#endif
}
#else
-static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
{
- uint idistx = 256 - distx;
- uint idisty = 256 - disty;
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+ const uint dx = distx>>8;
+ const uint dy = disty>>8;
+ const uint idx = 256 - dx;
+ const uint idy = 256 - dy;
+ QRgba64 xtop = interpolate256(t[0], idx, t[1], dx);
+ QRgba64 xbot = interpolate256(b[0], idx, b[1], dx);
+ return interpolate256(xtop, idy, xbot, dy);
}
#endif
-
template<TextureBlendType blendType>
void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2);
@@ -2102,10 +2519,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
int x2;
fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
}
@@ -2160,10 +2584,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
fy += fdy;
@@ -2245,10 +2676,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
fy += fdy;
@@ -2280,6 +2718,349 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
return buffer;
}
+template<TextureBlendType blendType>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
+ const QSpanData *data, int y, int x, int length)
+{
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
+
+ int image_width = data->texture.width;
+ int image_height = data->texture.height;
+
+ int image_x1 = data->texture.x1;
+ int image_y1 = data->texture.y1;
+ int image_x2 = data->texture.x2 - 1;
+ int image_y2 = data->texture.y2 - 1;
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
+ if (data->fast_matrix) {
+ // The increment pr x in the scanline
+ int fdx = (int)(data->m11 * fixed_scale);
+ int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+
+ if (fdy == 0) { //simple scale, no rotation
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ const uchar *s1 = data->texture.scanLine(y1);
+ const uchar *s2 = data->texture.scanLine(y2);
+
+ FetchPixelFunc fetch = qFetchPixel[layout->bpp];
+ uint sbuf1[buffer_size];
+ uint sbuf2[buffer_size];
+ QRgba64 buf1[buffer_size];
+ QRgba64 buf2[buffer_size];
+ QRgba64 *b = buffer;
+ while (length) {
+ int len = qMin(length, buffer_size / 2);
+ int fracX = fx;
+ int i = 0;
+ int disty = (fy & 0x0000ffff);
+#if defined(__SSE2__)
+ const __m128i vdy = _mm_set1_epi16(disty);
+ const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
+ if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
+ if (x1 != x2)
+ break;
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ fx += fdx;
+ }
+
+ const __m128i v_fdx = _mm_set1_epi32(fdx*4);
+ __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
+ for (; i < len-3; i+=4) {
+ int offset = _mm_extract_epi16(v_fx, 1);
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
+ offset = _mm_extract_epi16(v_fx, 3);
+ sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
+ offset = _mm_extract_epi16(v_fx, 5);
+ sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
+ offset = _mm_extract_epi16(v_fx, 7);
+ sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
+ v_fx = _mm_add_epi32(v_fx, v_fdx);
+ }
+ fx = _mm_cvtsi128_si32(v_fx);
+ }
+#endif
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
+
+ if (layout->bpp == QPixelLayout::BPP32) {
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+
+ } else {
+ sbuf1[i * 2 + 0] = fetch(s1, x1);
+ sbuf1[i * 2 + 1] = fetch(s1, x2);
+ sbuf2[i * 2 + 0] = fetch(s2, x1);
+ sbuf2[i * 2 + 1] = fetch(s2, x2);
+ }
+
+ fx += fdx;
+ }
+ layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
+ if (disty)
+ layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = (fracX & 0x0000ffff);
+#if defined(__SSE2__)
+ const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
+ __m128i vt = _mm_loadu_si128((const __m128i*)(buf1 + i*2));
+ if (disty) {
+ __m128i vb = _mm_loadu_si128((const __m128i*)(buf2 + i*2));
+ vt = _mm_mulhi_epu16(vt, vidy);
+ vb = _mm_mulhi_epu16(vb, vdy);
+ vt = _mm_add_epi16(vt, vb);
+ }
+ vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
+ vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
+ _mm_storel_epi64((__m128i*)(b+i), vt);
+#else
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+#endif
+ fracX += fdx;
+ }
+ length -= len;
+ b += len;
+ }
+ } else { //rotation
+ FetchPixelFunc fetch = qFetchPixel[layout->bpp];
+ uint sbuf1[buffer_size];
+ uint sbuf2[buffer_size];
+ QRgba64 buf1[buffer_size];
+ QRgba64 buf2[buffer_size];
+ QRgba64 *end = buffer + length;
+ QRgba64 *b = buffer;
+
+ while (b < end) {
+ int len = qMin(length, buffer_size / 2);
+ int fracX = fx;
+ int fracY = fy;
+ int i = 0;
+#if defined(__SSE2__)
+ if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ if (x1 != x2 && y1 != y2)
+ break;
+ const uchar *s1 = data->texture.scanLine(y1);
+ const uchar *s2 = data->texture.scanLine(y2);
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ fx += fdx;
+ fy += fdy;
+ }
+
+ const __m128i v_fdx = _mm_set1_epi32(fdx*4);
+ const __m128i v_fdy = _mm_set1_epi32(fdy*4);
+ __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
+ __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy);
+ const int bytesPerLine = data->texture.bytesPerLine;
+ const uchar *s1 = data->texture.imageData;
+ const uchar *s2 = s1 + bytesPerLine;
+ const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
+ for (; i < len-3; i+=4) {
+ if (fdx > 0 && (short)_mm_extract_epi16(v_fx, 7) >= image_x2)
+ break;
+ if (fdx < 0 && (short)_mm_extract_epi16(v_fx, 7) < image_x1)
+ break;
+ if (fdy > 0 && (short)_mm_extract_epi16(v_fy, 7) >= image_y2)
+ break;
+ if (fdy < 0 && (short)_mm_extract_epi16(v_fy, 7) < image_y1)
+ break;
+ const __m128i vy = _mm_packs_epi32(_mm_srai_epi32(v_fy, 16), _mm_setzero_si128());
+ __m128i voffset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epu16(vy, vbpl));
+ voffset = _mm_add_epi32(voffset, _mm_srli_epi32(v_fx, 16));
+
+ int offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
+ offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
+ sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
+ offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
+ sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
+ offset = _mm_cvtsi128_si32(voffset);
+ sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
+ sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
+ sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
+ sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
+
+ v_fx = _mm_add_epi32(v_fx, v_fdx);
+ v_fy = _mm_add_epi32(v_fy, v_fdy);
+ }
+ fx = _mm_cvtsi128_si32(v_fx);
+ fy = _mm_cvtsi128_si32(v_fy);
+ }
+#endif
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+
+ const uchar *s1 = data->texture.scanLine(y1);
+ const uchar *s2 = data->texture.scanLine(y2);
+
+ if (layout->bpp == QPixelLayout::BPP32) {
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+
+ } else {
+ sbuf1[i * 2 + 0] = fetch(s1, x1);
+ sbuf1[i * 2 + 1] = fetch(s1, x2);
+ sbuf2[i * 2 + 0] = fetch(s2, x1);
+ sbuf2[i * 2 + 1] = fetch(s2, x2);
+ }
+
+ fx += fdx;
+ fy += fdy;
+ }
+ layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
+ layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = (fracX & 0x0000ffff);
+ int disty = (fracY & 0x0000ffff);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ fracX += fdx;
+ fracY += fdy;
+ }
+
+ length -= len;
+ b += len;
+ }
+ }
+ } else {
+ qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
+ qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
+ qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+
+ FetchPixelFunc fetch = qFetchPixel[layout->bpp];
+ uint sbuf1[buffer_size];
+ uint sbuf2[buffer_size];
+ QRgba64 buf1[buffer_size];
+ QRgba64 buf2[buffer_size];
+ QRgba64 *b = buffer;
+
+ int distxs[buffer_size / 2];
+ int distys[buffer_size / 2];
+
+ while (length) {
+ int len = qMin(length, buffer_size / 2);
+ for (int i = 0; i < len; ++i) {
+ const qreal iw = fw == 0 ? 1 : 1 / fw;
+ const qreal px = fx * iw - qreal(0.5);
+ const qreal py = fy * iw - qreal(0.5);
+
+ int x1 = int(px) - (px < 0);
+ int x2;
+ int y1 = int(py) - (py < 0);
+ int y2;
+
+ distxs[i] = int((px - x1) * (1<<16));
+ distys[i] = int((py - y1) * (1<<16));
+
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+
+ const uchar *s1 = data->texture.scanLine(y1);
+ const uchar *s2 = data->texture.scanLine(y2);
+
+ if (layout->bpp == QPixelLayout::BPP32) {
+ sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+
+ } else {
+ sbuf1[i * 2 + 0] = fetch(s1, x1);
+ sbuf1[i * 2 + 1] = fetch(s1, x2);
+ sbuf2[i * 2 + 0] = fetch(s2, x1);
+ sbuf2[i * 2 + 1] = fetch(s2, x2);
+ }
+
+ fx += fdx;
+ fy += fdy;
+ fw += fdw;
+ //force increment to avoid /0
+ if (!fw)
+ fw += fdw;
+ }
+
+ layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
+ layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = distxs[i];
+ int disty = distys[i];
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ }
+
+ length -= len;
+ b += len;
+ }
+ }
+
+ return buffer;
+}
+
static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
// Untransformed
{
@@ -2448,6 +3229,174 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
},
};
+static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
+ // Untransformed
+ {
+ 0, // Invalid
+ fetchUntransformed64, // Mono
+ fetchUntransformed64, // MonoLsb
+ fetchUntransformed64, // Indexed8
+ fetchUntransformed64, // RGB32
+ fetchUntransformed64, // ARGB32
+ fetchUntransformed64, // ARGB32_Premultiplied
+ fetchUntransformed64, // RGB16
+ fetchUntransformed64, // ARGB8565_Premultiplied
+ fetchUntransformed64, // RGB666
+ fetchUntransformed64, // ARGB6666_Premultiplied
+ fetchUntransformed64, // RGB555
+ fetchUntransformed64, // ARGB8555_Premultiplied
+ fetchUntransformed64, // RGB888
+ fetchUntransformed64, // RGB444
+ fetchUntransformed64, // ARGB4444_Premultiplied
+ fetchUntransformed64, // RGBX8888
+ fetchUntransformed64, // RGBA8888
+ fetchUntransformed64, // RGBA8888_Premultiplied
+ fetchUntransformed64, // Format_BGR30
+ fetchUntransformed64, // Format_A2BGR30_Premultiplied
+ fetchUntransformed64, // Format_RGB30
+ fetchUntransformed64, // Format_A2RGB30_Premultiplied
+ fetchUntransformed64, // Alpha8
+ fetchUntransformed64, // Grayscale8
+ },
+ // Tiled
+ {
+ 0, // Invalid
+ fetchUntransformed64, // Mono
+ fetchUntransformed64, // MonoLsb
+ fetchUntransformed64, // Indexed8
+ fetchUntransformed64, // RGB32
+ fetchUntransformed64, // ARGB32
+ fetchUntransformed64, // ARGB32_Premultiplied
+ fetchUntransformed64, // RGB16
+ fetchUntransformed64, // ARGB8565_Premultiplied
+ fetchUntransformed64, // RGB666
+ fetchUntransformed64, // ARGB6666_Premultiplied
+ fetchUntransformed64, // RGB555
+ fetchUntransformed64, // ARGB8555_Premultiplied
+ fetchUntransformed64, // RGB888
+ fetchUntransformed64, // RGB444
+ fetchUntransformed64, // ARGB4444_Premultiplied
+ fetchUntransformed64, // RGBX8888
+ fetchUntransformed64, // RGBA8888
+ fetchUntransformed64, // RGBA8888_Premultiplied
+ fetchUntransformed64, // BGR30
+ fetchUntransformed64, // A2BGR30_Premultiplied
+ fetchUntransformed64, // RGB30
+ fetchUntransformed64, // A2RGB30_Premultiplied
+ fetchUntransformed64, // Alpha8
+ fetchUntransformed64, // Grayscale8
+ },
+ // Transformed
+ {
+ 0, // Invalid
+ fetchTransformed64<BlendTransformed>, // Mono
+ fetchTransformed64<BlendTransformed>, // MonoLsb
+ fetchTransformed64<BlendTransformed>, // Indexed8
+ fetchTransformed64<BlendTransformed>, // RGB32
+ fetchTransformed64<BlendTransformed>, // ARGB32
+ fetchTransformed64<BlendTransformed>, // ARGB32_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGB16
+ fetchTransformed64<BlendTransformed>, // ARGB8565_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGB666
+ fetchTransformed64<BlendTransformed>, // ARGB6666_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGB555
+ fetchTransformed64<BlendTransformed>, // ARGB8555_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGB888
+ fetchTransformed64<BlendTransformed>, // RGB444
+ fetchTransformed64<BlendTransformed>, // ARGB4444_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGBX8888
+ fetchTransformed64<BlendTransformed>, // RGBA8888
+ fetchTransformed64<BlendTransformed>, // RGBA8888_Premultiplied
+ fetchTransformed64<BlendTransformed>, // BGR30
+ fetchTransformed64<BlendTransformed>, // A2BGR30_Premultiplied
+ fetchTransformed64<BlendTransformed>, // RGB30
+ fetchTransformed64<BlendTransformed>, // A2RGB30_Premultiplied
+ fetchTransformed64<BlendTransformed>, // Alpah8
+ fetchTransformed64<BlendTransformed>, // Grayscale8
+ },
+ {
+ 0, // TransformedTiled
+ fetchTransformed64<BlendTransformedTiled>, // Mono
+ fetchTransformed64<BlendTransformedTiled>, // MonoLsb
+ fetchTransformed64<BlendTransformedTiled>, // Indexed8
+ fetchTransformed64<BlendTransformedTiled>, // RGB32
+ fetchTransformed64<BlendTransformedTiled>, // ARGB32
+ fetchTransformed64<BlendTransformedTiled>, // ARGB32_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGB16
+ fetchTransformed64<BlendTransformedTiled>, // ARGB8565_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGB666
+ fetchTransformed64<BlendTransformedTiled>, // ARGB6666_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGB555
+ fetchTransformed64<BlendTransformedTiled>, // ARGB8555_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGB888
+ fetchTransformed64<BlendTransformedTiled>, // RGB444
+ fetchTransformed64<BlendTransformedTiled>, // ARGB4444_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGBX8888
+ fetchTransformed64<BlendTransformedTiled>, // RGBA8888
+ fetchTransformed64<BlendTransformedTiled>, // RGBA8888_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // BGR30
+ fetchTransformed64<BlendTransformedTiled>, // A2BGR30_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // RGB30
+ fetchTransformed64<BlendTransformedTiled>, // A2RGB30_Premultiplied
+ fetchTransformed64<BlendTransformedTiled>, // Alpha8
+ fetchTransformed64<BlendTransformedTiled>, // Grayscale8
+ },
+ {
+ 0, // Bilinear
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // Mono
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // MonoLsb
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // Indexed8
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB32
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB32
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB32_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB16
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB666
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB555
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB888
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB444
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // ARGB4444_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBX8888
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBA8888
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGBA8888_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // BGR30
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // A2BGR30_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // RGB30
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // A2RGB30_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // Alpha8
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // Grayscale8
+ },
+ {
+ 0, // BilinearTiled
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Mono
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // MonoLsb
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Indexed8
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB32
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB32
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB32_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB16
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB666
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB555
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB888
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB444
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // ARGB4444_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBX8888
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBA8888
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGBA8888_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // BGR30
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // A2BGR30_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // RGB30
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // A2RGB30_Premultiplied
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Alpha8
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled>, // Grayscale8
+ },
+};
+
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
@@ -2476,78 +3425,50 @@ static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const Q
}
}
-static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
+class GradientBase32
{
- const uint *b = buffer;
- qreal t, inc;
-
- bool affine = true;
- qreal rx=0, ry=0;
- if (op->linear.l == 0) {
- t = inc = 0;
- } else {
- rx = data->m21 * (y + qreal(0.5)) + data->m11 * (x + qreal(0.5)) + data->dx;
- ry = data->m22 * (y + qreal(0.5)) + data->m12 * (x + qreal(0.5)) + data->dy;
- t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off;
- inc = op->linear.dx * data->m11 + op->linear.dy * data->m12;
- affine = !data->m13 && !data->m23;
-
- if (affine) {
- t *= (GRADIENT_STOPTABLE_SIZE - 1);
- inc *= (GRADIENT_STOPTABLE_SIZE - 1);
- }
+public:
+ typedef uint Type;
+ static Type null() { return 0; }
+ static Type fetchSingle(const QGradientData& gradient, qreal v)
+ {
+ return qt_gradient_pixel(&gradient, v);
}
-
- const uint *end = buffer + length;
- if (affine) {
- if (inc > qreal(-1e-5) && inc < qreal(1e-5)) {
- QT_MEMFILL_UINT(buffer, length, qt_gradient_pixel_fixed(&data->gradient, int(t * FIXPT_SIZE)));
- } else {
- if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) &&
- t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) {
- // we can use fixed point math
- int t_fixed = int(t * FIXPT_SIZE);
- int inc_fixed = int(inc * FIXPT_SIZE);
- while (buffer < end) {
- *buffer = qt_gradient_pixel_fixed(&data->gradient, t_fixed);
- t_fixed += inc_fixed;
- ++buffer;
- }
- } else {
- // we have to fall back to float math
- while (buffer < end) {
- *buffer = qt_gradient_pixel(&data->gradient, t/GRADIENT_STOPTABLE_SIZE);
- t += inc;
- ++buffer;
- }
- }
- }
- } else { // fall back to float math here as well
- qreal rw = data->m23 * (y + qreal(0.5)) + data->m13 * (x + qreal(0.5)) + data->m33;
- while (buffer < end) {
- qreal x = rx/rw;
- qreal y = ry/rw;
- t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off;
-
- *buffer = qt_gradient_pixel(&data->gradient, t);
- rx += data->m11;
- ry += data->m12;
- rw += data->m13;
- if (!rw) {
- rw += data->m13;
- }
- ++buffer;
- }
+ static Type fetchSingle(const QGradientData& gradient, int v)
+ {
+ return qt_gradient_pixel_fixed(&gradient, v);
}
+ static void memfill(Type *buffer, Type fill, int length)
+ {
+ qt_memfill32(buffer, fill, length);
+ }
+};
- return b;
-}
+class GradientBase64
+{
+public:
+ typedef QRgba64 Type;
+ static Type null() { return QRgba64::fromRgba64(0); }
+ static Type fetchSingle(const QGradientData& gradient, qreal v)
+ {
+ return qt_gradient_pixel64(&gradient, v);
+ }
+ static Type fetchSingle(const QGradientData& gradient, int v)
+ {
+ return qt_gradient_pixel64_fixed(&gradient, v);
+ }
+ static void memfill(Type *buffer, Type fill, int length)
+ {
+ qt_memfill64((quint64*)buffer, fill, length);
+ }
+};
-static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
+template<class GradientBase, typename BlendType>
+static inline const BlendType * QT_FASTCALL qt_fetch_linear_gradient_template(
+ BlendType *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
{
- const QRgba64 *b = buffer;
+ const BlendType *b = buffer;
qreal t, inc;
bool affine = true;
@@ -2567,11 +3488,10 @@ static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffe
}
}
- const QRgba64 *end = buffer + length;
+ const BlendType *end = buffer + length;
if (affine) {
if (inc > qreal(-1e-5) && inc < qreal(1e-5)) {
- QRgba64 color = qt_gradient_pixel64_fixed(&data->gradient, int(t * FIXPT_SIZE));
- qt_memfill64((quint64*)buffer, color, length);
+ GradientBase::memfill(buffer, GradientBase::fetchSingle(data->gradient, int(t * FIXPT_SIZE)), length);
} else {
if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) &&
t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) {
@@ -2579,14 +3499,14 @@ static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffe
int t_fixed = int(t * FIXPT_SIZE);
int inc_fixed = int(inc * FIXPT_SIZE);
while (buffer < end) {
- *buffer = qt_gradient_pixel64_fixed(&data->gradient, t_fixed);
+ *buffer = GradientBase::fetchSingle(data->gradient, t_fixed);
t_fixed += inc_fixed;
++buffer;
}
} else {
// we have to fall back to float math
while (buffer < end) {
- *buffer = qt_gradient_pixel64(&data->gradient, t/GRADIENT_STOPTABLE_SIZE);
+ *buffer = GradientBase::fetchSingle(data->gradient, t/GRADIENT_STOPTABLE_SIZE);
t += inc;
++buffer;
}
@@ -2599,7 +3519,7 @@ static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffe
qreal y = ry/rw;
t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off;
- *buffer = qt_gradient_pixel64(&data->gradient, t);
+ *buffer = GradientBase::fetchSingle(data->gradient, t);
rx += data->m11;
ry += data->m12;
rw += data->m13;
@@ -2613,6 +3533,18 @@ static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffe
return b;
}
+static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_linear_gradient_template<GradientBase32, uint>(buffer, op, data, y, x, length);
+}
+
+static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_linear_gradient_template<GradientBase64, QRgba64>(buffer, op, data, y, x, length);
+}
+
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x;
@@ -2627,19 +3559,22 @@ static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const Q
v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0;
}
-class RadialFetchPlain
+template <class GradientBase>
+class RadialFetchPlain : public GradientBase
{
public:
- static inline void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
- qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
+ typedef typename GradientBase::Type BlendType;
+ static void fetch(BlendType *buffer, BlendType *end,
+ const Operator *op, const QSpanData *data, qreal det,
+ qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
{
if (op->radial.extended) {
while (buffer < end) {
- quint32 result = 0;
+ BlendType result = GradientBase::null();
if (det >= 0) {
qreal w = qSqrt(det) - b;
if (data->gradient.radial.focal.radius + op->radial.dr * w >= 0)
- result = qt_gradient_pixel(&data->gradient, w);
+ result = GradientBase::fetchSingle(data->gradient, w);
}
*buffer = result;
@@ -2652,7 +3587,7 @@ public:
}
} else {
while (buffer < end) {
- *buffer++ = qt_gradient_pixel(&data->gradient, qSqrt(det) - b);
+ *buffer++ = GradientBase::fetchSingle(data->gradient, qSqrt(det) - b);
det += delta_det;
delta_det += delta_delta_det;
@@ -2665,15 +3600,23 @@ public:
const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
- return qt_fetch_radial_gradient_template<RadialFetchPlain>(buffer, op, data, y, x, length);
+ return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase32>, uint>(buffer, op, data, y, x, length);
}
static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain;
-static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+const QRgba64 * QT_FASTCALL qt_fetch_radial_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
{
- const uint *b = buffer;
+ return qt_fetch_radial_gradient_template<RadialFetchPlain<GradientBase64>, QRgba64>(buffer, op, data, y, x, length);
+}
+
+template <class GradientBase, typename BlendType>
+static inline const BlendType * QT_FASTCALL qt_fetch_conical_gradient_template(
+ BlendType *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const BlendType *b = buffer;
qreal rx = data->m21 * (y + qreal(0.5))
+ data->dx + data->m11 * (x + qreal(0.5));
qreal ry = data->m22 * (y + qreal(0.5))
@@ -2682,14 +3625,14 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op
const qreal inv2pi = M_1_PI / 2.0;
- const uint *end = buffer + length;
+ const BlendType *end = buffer + length;
if (affine) {
rx -= data->gradient.conical.center.x;
ry -= data->gradient.conical.center.y;
while (buffer < end) {
qreal angle = qAtan2(ry, rx) + data->gradient.conical.angle;
- *buffer = qt_gradient_pixel(&data->gradient, 1 - angle * inv2pi);
+ *buffer = GradientBase::fetchSingle(data->gradient, 1 - angle * inv2pi);
rx += data->m11;
ry += data->m12;
@@ -2705,7 +3648,7 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op
rx/rw - data->gradient.conical.center.y)
+ data->gradient.conical.angle;
- *buffer = qt_gradient_pixel(&data->gradient, 1 - angle * inv2pi);
+ *buffer = GradientBase::fetchSingle(data->gradient, 1 - angle * inv2pi);
rx += data->m11;
ry += data->m12;
@@ -2719,1905 +3662,29 @@ static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Op
return b;
}
-# define PRELOAD_INIT(x)
-# define PRELOAD_INIT2(x,y)
-# define PRELOAD_COND(x)
-# define PRELOAD_COND2(x,y)
-
-/* The constant alpha factor describes an alpha factor that gets applied
- to the result of the composition operation combining it with the destination.
-
- The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1.
- we get the unmodified operation
-
- result = src op dest
- dest = result * const_alpha + dest * (1. - const_alpha)
-
- This means that in the comments below, the first line is the const_alpha==255 case, the
- second line the general one.
-
- In the lines below:
- s == src, sa == alpha(src), sia = 1 - alpha(src)
- d == dest, da == alpha(dest), dia = 1 - alpha(dest)
- ca = const_alpha, cia = 1 - const_alpha
-
- The methods exist in two variants. One where we have a constant source, the other
- where the source is an array of pixels.
-*/
-
-/*
- result = 0
- d = d * cia
-*/
-#define comp_func_Clear_impl(dest, length, const_alpha)\
-{\
- if (const_alpha == 255) {\
- QT_MEMFILL_UINT(dest, length, 0);\
- } else {\
- int ialpha = 255 - const_alpha;\
- PRELOAD_INIT(dest)\
- for (int i = 0; i < length; ++i) {\
- PRELOAD_COND(dest)\
- dest[i] = BYTE_MUL(dest[i], ialpha);\
- }\
- }\
-}
-
-void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
-{
- comp_func_Clear_impl(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 {
- int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha255(dest[i], ialpha);
- }
- }
-}
-
-void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
-{
- comp_func_Clear_impl(dest, length, const_alpha);
-}
-
-void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
-{
- if (const_alpha == 255)
- qt_memfill64((quint64*)dest, 0, length);
- else {
- int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha255(dest[i], ialpha);
- }
- }
-}
-
-/*
- result = s
- dest = s * ca + d * cia
-*/
-void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha == 255) {
- QT_MEMFILL_UINT(dest, length, color);
- } else {
- int ialpha = 255 - const_alpha;
- color = BYTE_MUL(color, const_alpha);
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = color + BYTE_MUL(dest[i], ialpha);
- }
- }
-}
-
-void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha == 255)
- qt_memfill64((quint64*)dest, color, length);
- else {
- int ialpha = 255 - const_alpha;
- color = multiplyAlpha255(color, const_alpha);
- for (int i = 0; i < length; ++i) {
- dest[i] = color + multiplyAlpha255(dest[i], ialpha);
- }
- }
-}
-
-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, length * sizeof(uint));
- } else {
- int ialpha = 255 - const_alpha;
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
- }
- }
-}
-
-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, length * sizeof(quint64));
- else {
- int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = interpolate255(src[i], const_alpha, dest[i], ialpha);
- }
- }
-}
-
-void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
-{
-}
-
-void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint)
-{
-}
-
-void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint)
-{
-}
-
-void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint)
-{
-}
-
-/*
- result = s + d * sia
- dest = (s + d * sia) * ca + d * cia
- = 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)
-{
- if ((const_alpha & qAlpha(color)) == 255) {
- QT_MEMFILL_UINT(dest, length, color);
- } else {
- if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
- }
- }
-}
-
-void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha == 255 && color.isOpaque()) {
- qt_memfill64((quint64*)dest, color, length);
- } else {
- if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- for (int i = 0; i < length; ++i) {
- dest[i] = color + multiplyAlpha65535(dest[i], 65535 - color.alpha());
- }
- }
-}
-
-void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- 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) {
- PRELOAD_COND2(dest, src)
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
- }
- }
-}
-
-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())
- dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha());
- }
- } else {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = multiplyAlpha255(src[i], const_alpha);
- dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha());
- }
- }
-}
-
-/*
- result = d + s * dia
- 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);
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- 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)
-{
- if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- dest[i] = d + multiplyAlpha65535(color, 65535 - d.alpha());
- }
-}
-
-void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = d + BYTE_MUL(s, qAlpha(~d));
- }
- }
-}
-
-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) {
- QRgba64 d = dest[i];
- dest[i] = d + multiplyAlpha65535(src[i], 65535 - d.alpha());
- }
- } else {
- for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- QRgba64 s = multiplyAlpha255(src[i], const_alpha);
- dest[i] = d + multiplyAlpha65535(s, 65535 - d.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)
-{
- PRELOAD_INIT(dest)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
- }
- } else {
- color = BYTE_MUL(color, const_alpha);
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
- }
- }
-}
-
-void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
- }
- } else {
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
- }
- }
-}
-
-/*
- result = d * sa
- 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)
-{
- uint a = qAlpha(color);
- if (const_alpha != 255) {
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- }
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(dest[i], a);
- }
-}
-
-void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
- }
- } else {
- int cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], a);
- }
- }
-}
-
-/*
- 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)
-{
- PRELOAD_INIT(dest)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
- }
- } else {
- color = BYTE_MUL(color, const_alpha);
- int cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
- }
- }
-}
-
-void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
- }
- } else {
- int cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
- }
- }
-}
-
-/*
- result = d * sia
- 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)
-{
- uint a = qAlpha(~color);
- if (const_alpha != 255)
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = BYTE_MUL(dest[i], a);
- }
-}
-
-void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
- }
- } else {
- int cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], sia);
- }
- }
-}
-
-/*
- result = s*da + d*sia
- dest = s*da*ca + d*sia*ca + d *cia
- = 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);
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia);
- }
-}
-
-void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
- }
- }
-}
-
-/*
- result = d*sa + s*dia
- 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)
-{
- uint a = qAlpha(color);
- if (const_alpha != 255) {
- color = BYTE_MUL(color, const_alpha);
- a = qAlpha(color) + 255 - const_alpha;
- }
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
- }
-}
-
-void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
- }
- } else {
- int cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- 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));
- }
- }
-}
-
-/*
- result = d*sia + s*dia
- dest = d*sia*ca + s*dia*ca + d *cia
- = 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)
-{
- if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- uint sia = qAlpha(~color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~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)
-{
- PRELOAD_INIT2(dest, src)
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
- }
- }
-}
-
-struct QFullCoverage {
- inline void store(uint *dest, const uint src) const
- {
- *dest = src;
- }
-};
-
-struct QPartialCoverage {
- inline QPartialCoverage(uint const_alpha)
- : ca(const_alpha)
- , ica(255 - const_alpha)
- {
- }
-
- inline void store(uint *dest, const uint src) const
- {
- *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica);
- }
-
-private:
- const uint ca;
- const uint ica;
-};
-
-static inline int mix_alpha(int da, int sa)
-{
- return 255 - ((255 - sa) * (255 - da) >> 8);
-}
-
-/*
- 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)
-{
- uint s = color;
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- d = comp_func_Plus_one_pixel(d, s);
- coverage.store(&dest[i], d);
- }
-}
-
-void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, 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));
-}
-
-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)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- d = comp_func_Plus_one_pixel(d, s);
-
- coverage.store(&dest[i], d);
- }
-}
-
-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));
-}
-
-/*
- Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline int multiply_op(int dst, int src, int da, int sa)
-{
- return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) multiply_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) multiply_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
- = Sca + Dca - Sca.Dca
-*/
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Screen(uint *dest, const uint *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));
-}
-
-/*
- if 2.Dca < Da
- Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise
- Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline int overlay_op(int dst, int src, int da, int sa)
-{
- const int temp = src * (255 - da) + dst * (255 - sa);
- if (2 * dst < da)
- return qt_div_255(2 * src * dst + temp);
- else
- return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) overlay_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) overlay_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- Da' = Sa + Da - Sa.Da
-*/
-static inline int darken_op(int dst, int src, int da, int sa)
-{
- return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) darken_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) darken_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- Da' = Sa + Da - Sa.Da
-*/
-static inline int lighten_op(int dst, int src, int da, int sa)
-{
- return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) lighten_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) lighten_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- if Sca.Da + Dca.Sa >= Sa.Da
- Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise
- Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline int color_dodge_op(int dst, int src, int da, int sa)
-{
- const int sa_da = sa * da;
- const int dst_sa = dst * sa;
- const int src_da = src * da;
-
- const int temp = src * (255 - da) + dst * (255 - sa);
- if (src_da + dst_sa >= sa_da)
- return qt_div_255(sa_da + temp);
- else
- return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp);
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a,b) color_dodge_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) color_dodge_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- if Sca.Da + Dca.Sa <= Sa.Da
- Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise
- Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline int color_burn_op(int dst, int src, int da, int sa)
-{
- const int src_da = src * da;
- const int dst_sa = dst * sa;
- const int sa_da = sa * da;
-
- const int temp = src * (255 - da) + dst * (255 - sa);
-
- if (src == 0 || src_da + dst_sa <= sa_da)
- return qt_div_255(temp);
- return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp);
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) color_burn_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) color_burn_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- if 2.Sca < Sa
- Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise
- Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline uint hardlight_op(int dst, int src, int da, int sa)
-{
- const uint temp = src * (255 - da) + dst * (255 - sa);
-
- if (2 * src < sa)
- return qt_div_255(2 * src * dst + temp);
- else
- return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) hardlight_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) hardlight_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- if 2.Sca <= Sa
- Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise if 2.Sca > Sa and 4.Dca <= Da
- Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
- otherwise if 2.Sca > Sa and 4.Dca > Da
- Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-static inline int soft_light_op(int dst, int src, int da, int sa)
-{
- const int src2 = src << 1;
- const int dst_np = da != 0 ? (255 * dst) / da : 0;
- const int temp = (src * (255 - da) + dst * (255 - sa)) * 255;
-
- if (src2 < sa)
- return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025;
- else if (4 * dst <= da)
- return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
- else {
- return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
- }
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) soft_light_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) soft_light_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
- = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
-*/
-static inline int difference_op(int dst, int src, int da, int sa)
-{
- return src + dst - qt_div_255(2 * qMin(src * da, dst * sa));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) difference_op(a, b, da, sa)
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) difference_op(a, b, da, sa)
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-/*
- Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
-*/
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage)
-{
- int sa = qAlpha(color);
- int sr = qRed(color);
- int sg = qGreen(color);
- int sb = qBlue(color);
-
- PRELOAD_INIT(dest)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND(dest)
- uint d = dest[i];
- int da = qAlpha(d);
-
-#define OP(a, b) (a + b - qt_div_255(2*(a*b)))
- int r = OP( qRed(d), sr);
- int b = OP( qBlue(d), sb);
- int g = OP(qGreen(d), sg);
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint 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));
-}
-
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
-{
- PRELOAD_INIT2(dest, src)
- for (int i = 0; i < length; ++i) {
- PRELOAD_COND2(dest, src)
- uint d = dest[i];
- uint s = src[i];
-
- int da = qAlpha(d);
- int sa = qAlpha(s);
-
-#define OP(a, b) (a + b - ((a*b) >> 7))
- int r = OP( qRed(d), qRed(s));
- int b = OP( qBlue(d), qBlue(s));
- int g = OP(qGreen(d), qGreen(s));
- int a = mix_alpha(da, sa);
-#undef OP
-
- coverage.store(&dest[i], qRgba(r, g, b, a));
- }
-}
-
-void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *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));
-}
-
-void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--)
- *dest++ |= color;
-}
-
-void QT_FASTCALL rasterop_SourceOrDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--)
- *dest++ |= *src++;
-}
-
-void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color |= 0xff000000;
- while (length--)
- *dest++ &= color;
-}
-
-void QT_FASTCALL rasterop_SourceAndDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (*src & *dest) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color &= 0x00ffffff;
- while (length--)
- *dest++ ^= color;
-}
-
-void QT_FASTCALL rasterop_SourceXorDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (*src ^ *dest) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color = ~color;
- while (length--) {
- *dest = (color & ~(*dest)) | 0xff000000;
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (~(*src) & ~(*dest)) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color = ~color | 0xff000000;
- while (length--) {
- *dest = color | ~(*dest);
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = ~(*src) | ~(*dest) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color = ~color & 0x00ffffff;
- while (length--) {
- *dest = color ^ (*dest);
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_NotSourceXorDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = ((~(*src)) ^ (*dest)) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length,
- uint color, uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- qt_memfill(dest, ~color | 0xff000000, length);
-}
-
-void QT_FASTCALL rasterop_NotSource(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src,
- int length, uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--)
- *dest++ = ~(*src++) | 0xff000000;
-}
-
-void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- color = ~color | 0xff000000;
- while (length--) {
- *dest = color & *dest;
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_NotSourceAndDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (~(*src) & *dest) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (color & ~(*dest)) | 0xff000000;
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_SourceAndNotDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (*src & ~(*dest)) | 0xff000000;
- ++dest; ++src;
- }
-}
-
-void QT_FASTCALL rasterop_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
+static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (~(*src) | *dest) | 0xff000000;
- ++dest; ++src;
- }
+ return qt_fetch_conical_gradient_template<GradientBase32, uint>(buffer, data, y, x, length);
}
-void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *Q_DECL_RESTRICT dest,
- int length,
- uint color,
- uint const_alpha)
+static const QRgba64 * QT_FASTCALL qt_fetch_conical_gradient_rgb64(QRgba64 *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
- Q_UNUSED(const_alpha);
- color = ~color | 0xff000000;
- while (length--)
- *dest++ |= color;
+ return qt_fetch_conical_gradient_template<GradientBase64, QRgba64>(buffer, data, y, x, length);
}
-void QT_FASTCALL rasterop_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (*src | ~(*dest)) | 0xff000000;
- ++dest; ++src;
- }
-}
+extern CompositionFunctionSolid qt_functionForModeSolid_C[];
+extern CompositionFunctionSolid64 qt_functionForModeSolid64_C[];
-void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *Q_DECL_RESTRICT dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(const_alpha);
- while (length--) {
- *dest = (color | ~(*dest)) | 0xff000000;
- ++dest;
- }
-}
-
-void QT_FASTCALL rasterop_ClearDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(src);
- comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha);
-}
-
-void QT_FASTCALL rasterop_solid_ClearDestination(uint *Q_DECL_RESTRICT dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(color);
- comp_func_solid_SourceOver (dest, length, 0xff000000, const_alpha);
-}
-
-void QT_FASTCALL rasterop_SetDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(src);
- comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha);
-}
-
-void QT_FASTCALL rasterop_solid_SetDestination(uint *Q_DECL_RESTRICT dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(color);
- comp_func_solid_SourceOver (dest, length, 0xffffffff, const_alpha);
-}
-
-void QT_FASTCALL rasterop_NotDestination(uint *Q_DECL_RESTRICT dest,
- const uint *Q_DECL_RESTRICT src,
- int length,
- uint const_alpha)
-{
- Q_UNUSED(src);
- rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha);
-}
-
-void QT_FASTCALL rasterop_solid_NotDestination(uint *Q_DECL_RESTRICT dest,
- int length,
- uint color,
- uint const_alpha)
-{
- Q_UNUSED(color);
- rasterop_solid_SourceXorDestination (dest, length, 0x00ffffff, const_alpha);
-}
-
-static CompositionFunctionSolid functionForModeSolid_C[] = {
- comp_func_solid_SourceOver,
- comp_func_solid_DestinationOver,
- comp_func_solid_Clear,
- comp_func_solid_Source,
- comp_func_solid_Destination,
- comp_func_solid_SourceIn,
- comp_func_solid_DestinationIn,
- comp_func_solid_SourceOut,
- comp_func_solid_DestinationOut,
- comp_func_solid_SourceAtop,
- comp_func_solid_DestinationAtop,
- comp_func_solid_XOR,
- comp_func_solid_Plus,
- comp_func_solid_Multiply,
- comp_func_solid_Screen,
- comp_func_solid_Overlay,
- comp_func_solid_Darken,
- comp_func_solid_Lighten,
- comp_func_solid_ColorDodge,
- comp_func_solid_ColorBurn,
- comp_func_solid_HardLight,
- comp_func_solid_SoftLight,
- comp_func_solid_Difference,
- comp_func_solid_Exclusion,
- rasterop_solid_SourceOrDestination,
- rasterop_solid_SourceAndDestination,
- rasterop_solid_SourceXorDestination,
- rasterop_solid_NotSourceAndNotDestination,
- rasterop_solid_NotSourceOrNotDestination,
- rasterop_solid_NotSourceXorDestination,
- rasterop_solid_NotSource,
- rasterop_solid_NotSourceAndDestination,
- rasterop_solid_SourceAndNotDestination,
- rasterop_solid_NotSourceOrDestination,
- rasterop_solid_SourceOrNotDestination,
- rasterop_solid_ClearDestination,
- rasterop_solid_SetDestination,
- rasterop_solid_NotDestination
-};
+static const CompositionFunctionSolid *functionForModeSolid = qt_functionForModeSolid_C;
+static const CompositionFunctionSolid64 *functionForModeSolid64 = qt_functionForModeSolid64_C;
-static CompositionFunctionSolid64 functionForModeSolid64_C[] = {
- comp_func_solid_SourceOver_rgb64,
- comp_func_solid_DestinationOver_rgb64,
- comp_func_solid_Clear_rgb64,
- comp_func_solid_Source_rgb64,
- comp_func_solid_Destination_rgb64,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
-static const CompositionFunctionSolid64 *functionForModeSolid64 = functionForModeSolid64_C;
-
-static CompositionFunction functionForMode_C[] = {
- comp_func_SourceOver,
- comp_func_DestinationOver,
- comp_func_Clear,
- comp_func_Source,
- comp_func_Destination,
- comp_func_SourceIn,
- comp_func_DestinationIn,
- comp_func_SourceOut,
- comp_func_DestinationOut,
- comp_func_SourceAtop,
- comp_func_DestinationAtop,
- comp_func_XOR,
- comp_func_Plus,
- comp_func_Multiply,
- comp_func_Screen,
- comp_func_Overlay,
- comp_func_Darken,
- comp_func_Lighten,
- comp_func_ColorDodge,
- comp_func_ColorBurn,
- comp_func_HardLight,
- comp_func_SoftLight,
- comp_func_Difference,
- comp_func_Exclusion,
- rasterop_SourceOrDestination,
- rasterop_SourceAndDestination,
- rasterop_SourceXorDestination,
- rasterop_NotSourceAndNotDestination,
- rasterop_NotSourceOrNotDestination,
- rasterop_NotSourceXorDestination,
- rasterop_NotSource,
- rasterop_NotSourceAndDestination,
- rasterop_SourceAndNotDestination,
- rasterop_NotSourceOrDestination,
- rasterop_SourceOrNotDestination,
- rasterop_ClearDestination,
- rasterop_SetDestination,
- rasterop_NotDestination
-};
-
-static CompositionFunction64 functionForMode64_C[] = {
- comp_func_SourceOver_rgb64,
- comp_func_DestinationOver_rgb64,
- comp_func_Clear_rgb64,
- comp_func_Source_rgb64,
- comp_func_Destination_rgb64,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
+extern CompositionFunction qt_functionForMode_C[];
+extern CompositionFunction64 qt_functionForMode64_C[];
-static const CompositionFunction *functionForMode = functionForMode_C;
-static const CompositionFunction64 *functionForMode64 = functionForMode64_C;
+static const CompositionFunction *functionForMode = qt_functionForMode_C;
+static const CompositionFunction64 *functionForMode64 = qt_functionForMode64_C;
static TextureBlendType getBlendType(const QSpanData *data)
{
@@ -4648,6 +3715,8 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
switch(data->type) {
case QSpanData::Solid:
solidSource = data->solid.color.isOpaque();
+ op.srcFetch = 0;
+ op.srcFetch64 = 0;
break;
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
@@ -4659,18 +3728,20 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
solidSource = !data->gradient.alphaColor;
getRadialGradientValues(&op.radial, data);
op.srcFetch = qt_fetch_radial_gradient;
- op.srcFetch64 = 0; //qt_fetch_radial_gradient_rgb64;
+ op.srcFetch64 = qt_fetch_radial_gradient_rgb64;
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
op.srcFetch = qt_fetch_conical_gradient;
- op.srcFetch64 = 0; //qt_fetch_conical_gradient_rgb64;
+ op.srcFetch64 = qt_fetch_conical_gradient_rgb64;
break;
case QSpanData::Texture:
- op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format];
- op.srcFetch64 = 0; // sourceFetch64[getBlendType(data)][data->texture.format];
solidSource = !data->texture.hasAlpha;
+ op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format];
+ op.srcFetch64 = sourceFetch64[getBlendType(data)][data->texture.format];
+ break;
default:
+ Q_UNREACHABLE();
break;
}
@@ -4698,10 +3769,8 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
}
++spans;
}
- if (!alphaSpans) {
+ if (!alphaSpans)
op.destFetch = 0;
- op.destFetch64 = 0;
- }
}
}
}
@@ -4795,10 +3864,9 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
int length = spans->len;
while (length) {
int l = qMin(buffer_size, length);
- QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.funcSolid64(dest, l, color, spans->coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
length -= l;
x += l;
}
@@ -4987,7 +4055,7 @@ public:
bool isSupported() const
{
- return op.srcFetch64 && op.func64;
+ return op.func64 && op.destFetch64 && op.destStore64;
}
const QRgba64 *fetch(int x, int y, int len)
@@ -5078,7 +4146,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
- if (!op.srcFetch64 || !op.func64) {
+ if (!op.func64) {
qWarning() << Q_FUNC_INFO << "Unsupported blend";
return blend_untransformed_generic(count, spans, userData);
}
@@ -5108,10 +4176,9 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
while (length) {
int l = qMin(buffer_size, length);
const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -5320,7 +4387,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
- if (!op.srcFetch64 || !op.func64) {
+ if (!op.func64) {
qDebug("unsupported rgb64 blend");
return blend_tiled_generic(count, spans, userData);
}
@@ -5353,10 +4420,9 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
if (buffer_size < l)
l = buffer_size;
const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -6568,6 +5634,16 @@ inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer,
map, mapWidth, mapHeight, mapStride);
}
+template<QtPixelOrder PixelOrder>
+inline static void qt_bitmapblit_rgb30(QRasterBuffer *rasterBuffer,
+ int x, int y, const QRgba64 &color,
+ const uchar *map,
+ int mapWidth, int mapHeight, int mapStride)
+{
+ qt_bitmapblit_template<quint32>(rasterBuffer, x, y, qConvertRgb64ToRgb30<PixelOrder>(color),
+ map, mapWidth, mapHeight, mapStride);
+}
+
inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
@@ -7090,7 +6166,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
{
blend_color_generic_rgb64,
blend_src_generic_rgb64,
- 0,
+ qt_bitmapblit_rgb30<PixelOrderBGR>,
0,
0,
qt_rectfill_rgb30<PixelOrderBGR>
@@ -7099,7 +6175,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
{
blend_color_generic_rgb64,
blend_src_generic_rgb64,
- 0,
+ qt_bitmapblit_rgb30<PixelOrderBGR>,
0,
0,
qt_rectfill_rgb30<PixelOrderBGR>
@@ -7108,7 +6184,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
{
blend_color_generic_rgb64,
blend_src_generic_rgb64,
- 0,
+ qt_bitmapblit_rgb30<PixelOrderRGB>,
0,
0,
qt_rectfill_rgb30<PixelOrderRGB>
@@ -7117,7 +6193,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
{
blend_color_generic_rgb64,
blend_src_generic_rgb64,
- 0,
+ qt_bitmapblit_rgb30<PixelOrderRGB>,
0,
0,
qt_rectfill_rgb30<PixelOrderRGB>
@@ -7217,9 +6293,6 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
void qInitDrawhelperAsm()
{
- CompositionFunction *functionForModeAsm = 0;
- CompositionFunctionSolid *functionForModeSolidAsm = 0;
-
const uint features = qCpuFeatures();
Q_UNUSED(features);
#ifdef __SSE2__
@@ -7304,9 +6377,15 @@ void qInitDrawhelperAsm()
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2;
}
#endif
+ extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha);
+ extern void QT_FASTCALL comp_func_Source_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_Plus_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_sse2;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_sse2;
+ qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_sse2;
+ qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2;
- functionForModeAsm = qt_functionForMode_SSE2;
- functionForModeSolidAsm = qt_functionForModeSolid_SSE2;
#endif // SSE2
#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
@@ -7332,9 +6411,9 @@ void qInitDrawhelperAsm()
qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
- functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
- functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon;
- functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon;
+ qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon;
destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
@@ -7354,25 +6433,25 @@ void qInitDrawhelperAsm()
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
if (features & (DSP | DSPR2)) {
// Composition functions are all DSP r1
- functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_SourceIn] = comp_func_SourceIn_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_DestinationIn] = comp_func_DestinationIn_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_DestinationOut] = comp_func_DestinationOut_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_SourceAtop] = comp_func_SourceAtop_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_DestinationAtop] = comp_func_DestinationAtop_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_Xor] = comp_func_XOR_mips_dsp;
- functionForMode_C[QPainter::CompositionMode_SourceOut] = comp_func_SourceOut_mips_dsp;
-
- functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_DestinationOver] = comp_func_solid_DestinationOver_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_SourceIn] = comp_func_solid_SourceIn_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_DestinationIn] = comp_func_solid_DestinationIn_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_SourceAtop] = comp_func_solid_SourceAtop_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_DestinationAtop] = comp_func_solid_DestinationAtop_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp;
- functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationOver] = comp_func_DestinationOver_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceIn] = comp_func_SourceIn_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationIn] = comp_func_DestinationIn_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationOut] = comp_func_DestinationOut_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceAtop] = comp_func_SourceAtop_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_DestinationAtop] = comp_func_DestinationAtop_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_Xor] = comp_func_XOR_mips_dsp;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOut] = comp_func_SourceOut_mips_dsp;
+
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationOver] = comp_func_solid_DestinationOver_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceIn] = comp_func_solid_SourceIn_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationIn] = comp_func_solid_DestinationIn_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceAtop] = comp_func_solid_SourceAtop_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_DestinationAtop] = comp_func_solid_DestinationAtop_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_Xor] = comp_func_solid_XOR_mips_dsp;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOut] = comp_func_solid_SourceOut_mips_dsp;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mips_dsp;
@@ -7399,20 +6478,6 @@ void qInitDrawhelperAsm()
#endif // QT_COMPILER_SUPPORTS_MIPS_DSPR2
}
#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
-
- if (functionForModeSolidAsm) {
- const int destinationMode = QPainter::CompositionMode_Destination;
- functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode];
-
- // use the default qdrawhelper implementation for the
- // extended composition modes
- for (int mode = 12; mode < 24; ++mode)
- functionForModeSolidAsm[mode] = functionForModeSolid_C[mode];
-
- functionForModeSolid = functionForModeSolidAsm;
- }
- if (functionForModeAsm)
- functionForMode = functionForModeAsm;
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 36e2488a94..08e564f017 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -986,7 +986,7 @@ public:
const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
- return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon> >(buffer, op, data, y, x, length);
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon>,uint>(buffer, op, data, y, x, length);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 501f1ce033..f8865a6f7e 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -395,24 +395,24 @@ static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
return (b * b) - (4 * a * c);
}
-template <class RadialFetchFunc> Q_STATIC_TEMPLATE_FUNCTION
-const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
+template <class RadialFetchFunc, typename BlendType> static
+const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffer, const Operator *op,
+ const QSpanData *data, int y, int x, int length)
{
// avoid division by zero
if (qFuzzyIsNull(op->radial.a)) {
- qt_memfill32(buffer, 0, length);
+ RadialFetchFunc::memfill(buffer, RadialFetchFunc::null(), length);
return buffer;
}
- const uint *b = buffer;
+ const BlendType *b = buffer;
qreal rx = data->m21 * (y + qreal(0.5))
+ data->dx + data->m11 * (x + qreal(0.5));
qreal ry = data->m22 * (y + qreal(0.5))
+ data->dy + data->m12 * (x + qreal(0.5));
bool affine = !data->m13 && !data->m23;
- uint *end = buffer + length;
+ BlendType *end = buffer + length;
if (affine) {
rx -= data->gradient.radial.focal.x;
ry -= data->gradient.radial.focal.y;
@@ -459,7 +459,7 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const O
qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + gx*op->radial.dx + gy*op->radial.dy);
qreal det = qRadialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy));
- quint32 result = 0;
+ BlendType result = RadialFetchFunc::null();
if (det >= 0) {
qreal detSqrt = qSqrt(det);
@@ -469,7 +469,7 @@ const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const O
qreal s = qMax(s0, s1);
if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0)
- result = qt_gradient_pixel(&data->gradient, s);
+ result = RadialFetchFunc::fetchSingle(data->gradient, s);
}
*buffer = result;
@@ -490,6 +490,15 @@ template <class Simd>
class QRadialFetchSimd
{
public:
+ static uint null() { return 0; }
+ static uint fetchSingle(const QGradientData& gradient, qreal v)
+ {
+ return qt_gradient_pixel(&gradient, v);
+ }
+ static void memfill(uint *buffer, uint fill, int length)
+ {
+ qt_memfill32(buffer, fill, length);
+ }
static void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
{
@@ -625,6 +634,42 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
}
#endif
+#ifdef __SSE2__
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ // First interpolate right and left pixels in parallel.
+ __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl));
+ __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br));
+ vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128());
+ vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128());
+ vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx));
+ vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx));
+ __m128i vtb = _mm_add_epi16(vl, vr);
+ vtb = _mm_srli_epi16(vtb, 8);
+ // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop)
+
+ // Now the last interpolate between top and bottom interpolations.
+ const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty);
+ vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8));
+ // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb }
+ vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add.
+ vtb = _mm_srli_epi32(vtb, 8);
+ vtb = _mm_packs_epi32(vtb, _mm_setzero_si128());
+ vtb = _mm_packus_epi16(vtb, _mm_setzero_si128());
+ return _mm_cvtsi128_si32(vtb);
+}
+#else
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ uint idistx = 256 - distx;
+ uint idisty = 256 - disty;
+ uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
+ uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
+ return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+}
+#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
@@ -1056,89 +1101,11 @@ inline int comp_func_Plus_one_pixel(uint d, const uint s)
#undef MIX
#undef AMIX
-// prototypes of all the composition functions
-void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint);
-void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotSourceOrDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SourceOrNotDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_ClearDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_SetDestination(uint *dest, const uint *src, int length, uint const_alpha);
-void QT_FASTCALL rasterop_NotDestination(uint *dest, const uint *src, int length, uint const_alpha);
-// prototypes of all the solid composition functions
-void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Destination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotSourceOrDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SourceOrNotDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_ClearDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_SetDestination(uint *dest, int length, uint color, uint const_alpha);
-void QT_FASTCALL rasterop_solid_NotDestination(uint *dest, int length, uint color, uint const_alpha);
-
-
struct QPixelLayout;
typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
const QPixelLayout *layout, const QRgb *clut);
+typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count,
+ const QPixelLayout *layout, const QRgb *clut);
struct QPixelLayout
{
@@ -1168,6 +1135,7 @@ struct QPixelLayout
ConvertFunc convertToARGB32PM;
ConvertFunc convertFromARGB32PM;
ConvertFunc convertFromRGB32;
+ ConvertFunc64 convertToARGB64PM;
};
typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index b8957fe2fb..d7f3686e54 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -311,90 +311,6 @@ void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, u
}
}
-#ifndef QDRAWHELPER_AVX
-CompositionFunctionSolid qt_functionForModeSolid_SSE2[numCompositionFunctions] = {
- comp_func_solid_SourceOver_sse2,
- comp_func_solid_DestinationOver,
- comp_func_solid_Clear,
- comp_func_solid_Source,
- comp_func_solid_Destination,
- comp_func_solid_SourceIn,
- comp_func_solid_DestinationIn,
- comp_func_solid_SourceOut,
- comp_func_solid_DestinationOut,
- comp_func_solid_SourceAtop,
- comp_func_solid_DestinationAtop,
- comp_func_solid_XOR,
- comp_func_solid_Plus,
- comp_func_solid_Multiply,
- comp_func_solid_Screen,
- comp_func_solid_Overlay,
- comp_func_solid_Darken,
- comp_func_solid_Lighten,
- comp_func_solid_ColorDodge,
- comp_func_solid_ColorBurn,
- comp_func_solid_HardLight,
- comp_func_solid_SoftLight,
- comp_func_solid_Difference,
- comp_func_solid_Exclusion,
- rasterop_solid_SourceOrDestination,
- rasterop_solid_SourceAndDestination,
- rasterop_solid_SourceXorDestination,
- rasterop_solid_NotSourceAndNotDestination,
- rasterop_solid_NotSourceOrNotDestination,
- rasterop_solid_NotSourceXorDestination,
- rasterop_solid_NotSource,
- rasterop_solid_NotSourceAndDestination,
- rasterop_solid_SourceAndNotDestination,
- rasterop_solid_NotSourceOrDestination,
- rasterop_solid_SourceOrNotDestination,
- rasterop_solid_ClearDestination,
- rasterop_solid_SetDestination,
- rasterop_solid_NotDestination
-};
-
-CompositionFunction qt_functionForMode_SSE2[numCompositionFunctions] = {
- comp_func_SourceOver_sse2,
- comp_func_DestinationOver,
- comp_func_Clear,
- comp_func_Source_sse2,
- comp_func_Destination,
- comp_func_SourceIn,
- comp_func_DestinationIn,
- comp_func_SourceOut,
- comp_func_DestinationOut,
- comp_func_SourceAtop,
- comp_func_DestinationAtop,
- comp_func_XOR,
- comp_func_Plus_sse2,
- comp_func_Multiply,
- comp_func_Screen,
- comp_func_Overlay,
- comp_func_Darken,
- comp_func_Lighten,
- comp_func_ColorDodge,
- comp_func_ColorBurn,
- comp_func_HardLight,
- comp_func_SoftLight,
- comp_func_Difference,
- comp_func_Exclusion,
- rasterop_SourceOrDestination,
- rasterop_SourceAndDestination,
- rasterop_SourceXorDestination,
- rasterop_NotSourceAndNotDestination,
- rasterop_NotSourceOrNotDestination,
- rasterop_NotSourceXorDestination,
- rasterop_NotSource,
- rasterop_NotSourceAndDestination,
- rasterop_SourceAndNotDestination,
- rasterop_NotSourceOrDestination,
- rasterop_SourceOrNotDestination,
- rasterop_ClearDestination,
- rasterop_SetDestination,
- rasterop_NotDestination
-};
-#endif
-
void qt_memfill16(quint16 *dest, quint16 value, int count)
{
if (count < 3) {
@@ -550,7 +466,7 @@ public:
const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
int y, int x, int length)
{
- return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2> >(buffer, op, data, y, x, length);
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2>,uint>(buffer, op, data, y, x, length);
}
void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index 4d0790a502..1a7dddf0d5 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -242,6 +242,8 @@ QT_FUNCTION_TARGET(SSE4_1)
inline QRgb qUnpremultiply_sse4(QRgb p)
{
const uint alpha = qAlpha(p);
+ if (alpha == 255 || alpha == 0)
+ return p;
const uint invAlpha = qt_inv_premul_factor[alpha];
const __m128i via = _mm_set1_epi32(invAlpha);
const __m128i vr = _mm_set1_epi32(0x8000);
@@ -250,8 +252,8 @@ inline QRgb qUnpremultiply_sse4(QRgb p)
vl = _mm_add_epi32(vl, vr);
vl = _mm_srai_epi32(vl, 16);
vl = _mm_insert_epi32(vl, alpha, 3);
- vl = _mm_packus_epi32(vl, _mm_setzero_si128());
- vl = _mm_packus_epi16(vl, _mm_setzero_si128());
+ vl = _mm_packus_epi32(vl, vl);
+ vl = _mm_packus_epi16(vl, vl);
return _mm_cvtsi128_si32(vl);
}
#endif
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 58e9112dd6..5f1b25e189 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -38,10 +38,6 @@
QT_BEGIN_NAMESPACE
-namespace QImageScale {
- struct QImageScaleInfo;
-}
-
typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
@@ -105,15 +101,7 @@ qt_qimageScaleFunc qt_qimageScaleRgb = qt_qimageScaleAARGB;
namespace QImageScale {
- struct QImageScaleInfo {
- int *xpoints;
- const unsigned int **ypoints;
- int *xapoints, *yapoints;
- int xup_yup;
- };
-
- const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh,
- int dh);
+ const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
int* qimageCalcXPoints(int sw, int dw);
int* qimageCalcApoints(int s, int d, int up);
QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
@@ -134,16 +122,11 @@ using namespace QImageScale;
#define G_VAL(p) (qGreen(*p))
#define B_VAL(p) (qBlue(*p))
-#define INV_XAP (256 - xapoints[x])
-#define XAP (xapoints[x])
-#define INV_YAP (256 - yapoints[dyy + y])
-#define YAP (yapoints[dyy + y])
-
const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int sw, int sh, int dh)
{
const unsigned int **p;
- int i, j = 0, rv = 0;
+ int j = 0, rv = 0;
qint64 val, inc;
if(dh < 0){
@@ -155,12 +138,12 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int up = qAbs(dh) >= sh;
val = up ? 0x8000 * sh / dh - 0x8000 : 0;
inc = (((qint64)sh) << 16) / dh;
- for(i = 0; i < dh; i++){
+ for (int i = 0; i < dh; i++) {
p[j++] = src + qMax(0LL, val >> 16) * sw;
val += inc;
}
- if(rv){
- for(i = dh / 2; --i >= 0; ){
+ if (rv) {
+ for (int i = dh / 2; --i >= 0; ) {
const unsigned int *tmp = p[i];
p[i] = p[dh - i - 1];
p[dh - i - 1] = tmp;
@@ -171,7 +154,7 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int* QImageScale::qimageCalcXPoints(int sw, int dw)
{
- int *p, i, j = 0, rv = 0;
+ int *p, j = 0, rv = 0;
qint64 val, inc;
if(dw < 0){
@@ -183,13 +166,13 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
int up = qAbs(dw) >= sw;
val = up ? 0x8000 * sw / dw - 0x8000 : 0;
inc = (((qint64)sw) << 16) / dw;
- for(i = 0; i < dw; i++){
+ for (int i = 0; i < dw; i++) {
p[j++] = qMax(0LL, val >> 16);
val += inc;
}
- if(rv){
- for(i = dw / 2; --i >= 0; ){
+ if (rv) {
+ for (int i = dw / 2; --i >= 0; ) {
int tmp = p[i];
p[i] = p[dw - i - 1];
p[dw - i - 1] = tmp;
@@ -200,7 +183,7 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
int* QImageScale::qimageCalcApoints(int s, int d, int up)
{
- int *p, i, j = 0, rv = 0;
+ int *p, j = 0, rv = 0;
if(d < 0){
rv = 1;
@@ -214,7 +197,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
val = 0x8000 * s / d - 0x8000;
inc = (((qint64)s) << 16) / d;
- for(i = 0; i < d; i++){
+ for (int i = 0; i < d; i++) {
int pos = val >> 16;
if (pos < 0)
p[j++] = 0;
@@ -226,14 +209,12 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
}
}
/* scaling down */
- else{
- qint64 val, inc;
- int ap, Cp;
- val = 0;
- inc = (((qint64)s) << 16) / d;
- Cp = ((d << 14) / s) + 1;
- for(i = 0; i < d; i++){
- ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
+ else {
+ qint64 val = 0;
+ qint64 inc = (((qint64)s) << 16) / d;
+ int Cp = (((d << 14) + s - 1) / s);
+ for (int i = 0; i < d; i++) {
+ int ap = ((0x10000 - (val & 0xffff)) * Cp) >> 16;
p[j] = ap | (Cp << 16);
j++;
val += inc;
@@ -241,13 +222,13 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
}
if(rv){
int tmp;
- for(i = d / 2; --i >= 0; ){
+ for (int i = d / 2; --i >= 0; ) {
tmp = p[i];
p[i] = p[d - i - 1];
p[d - i - 1] = tmp;
}
}
- return(p);
+ return p;
}
QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
@@ -297,700 +278,500 @@ QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
return(isi);
}
-/* FIXME: NEED to optimize ScaleAARGBA - currently its "ok" but needs work*/
-/* scale by area sampling */
-static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
+template<bool RGB>
+void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+#endif
+
+static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
{
- const unsigned int *sptr;
- unsigned int *dptr;
- int x, y, end;
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
- end = dxx + dw;
- /* scaling up both ways */
- if(isi->xup_yup == 3){
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- /* calculate the source line we'll scan from */
- dptr = dest + dx + ((y + dy) * dow);
- sptr = ypoints[dyy + y];
- if(YAP > 0){
- for(x = dxx; x < end; x++){
- int r, g, b, a;
- int rr, gg, bb, aa;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- a = A_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- a += A_VAL(pix) * XAP;
- pix += sow;
- rr = R_VAL(pix) * XAP;
- gg = G_VAL(pix) * XAP;
- bb = B_VAL(pix) * XAP;
- aa = A_VAL(pix) * XAP;
- pix--;
- rr += R_VAL(pix) * INV_XAP;
- gg += G_VAL(pix) * INV_XAP;
- bb += B_VAL(pix) * INV_XAP;
- aa += A_VAL(pix) * INV_XAP;
- r = ((rr * YAP) + (r * INV_YAP)) >> 16;
- g = ((gg * YAP) + (g * INV_YAP)) >> 16;
- b = ((bb * YAP) + (b * INV_YAP)) >> 16;
- a = ((aa * YAP) + (a * INV_YAP)) >> 16;
- *dptr++ = qRgba(r, g, b, a);
- }
- else{
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_YAP;
- g = G_VAL(pix) * INV_YAP;
- b = B_VAL(pix) * INV_YAP;
- a = A_VAL(pix) * INV_YAP;
- pix += sow;
- r += R_VAL(pix) * YAP;
- g += G_VAL(pix) * YAP;
- b += B_VAL(pix) * YAP;
- a += A_VAL(pix) * YAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- a >>= 8;
- *dptr++ = qRgba(r, g, b, a);
- }
- }
+ int end = dxx + dw;
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ /* calculate the source line we'll scan from */
+ const unsigned int *sptr = ypoints[dyy + y];
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ const int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_4_pixels(pix[0], pix[1], pix[sow], pix[sow + 1], xap, yap);
+ else
+ *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap);
+ dptr++;
}
- else{
- for(x = dxx; x < end; x++){
- int r, g, b, a;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- a = A_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- a += A_VAL(pix) * XAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- a >>= 8;
- *dptr++ = qRgba(r, g, b, a);
- }
- else
- *dptr++ = sptr[xpoints[x] ];
- }
+ } else {
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
+ dptr++;
}
}
}
+}
+
+/* scale by area sampling */
+static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ /* scaling up both ways */
+ if (isi->xup_yup == 3){
+ qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
/* if we're scaling down vertically */
- else if(isi->xup_yup == 1){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cy, j;
- const unsigned int *pix;
- int r, g, b, a, rr, gg, bb, aa;
- int yap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- a = A_VAL(pix) * yap;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix += sow;
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- a += A_VAL(pix) * Cy;
- }
- if(j > 0){
- pix += sow;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
- }
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + 1;
- rr = R_VAL(pix) * yap;
- gg = G_VAL(pix) * yap;
- bb = B_VAL(pix) * yap;
- aa = A_VAL(pix) * yap;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix += sow;
- rr += R_VAL(pix) * Cy;
- gg += G_VAL(pix) * Cy;
- bb += B_VAL(pix) * Cy;
- aa += A_VAL(pix) * Cy;
- }
- if(j > 0){
- pix += sow;
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- aa += A_VAL(pix) * j;
- }
- r = r * INV_XAP;
- g = g * INV_XAP;
- b = b * INV_XAP;
- a = a * INV_XAP;
- r = (r + ((rr * XAP))) >> 12;
- g = (g + ((gg * XAP))) >> 12;
- b = (b + ((bb * XAP))) >> 12;
- a = (a + ((aa * XAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- a >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 1) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally */
- else if(isi->xup_yup == 2){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, j;
- const unsigned int *pix;
- int r, g, b, a, rr, gg, bb, aa;
- int xap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
- a = A_VAL(pix) * xap;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- pix++;
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- a += A_VAL(pix) * Cx;
- }
- if(j > 0){
- pix++;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
- }
- if(YAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + sow;
- rr = R_VAL(pix) * xap;
- gg = G_VAL(pix) * xap;
- bb = B_VAL(pix) * xap;
- aa = A_VAL(pix) * xap;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- pix++;
- rr += R_VAL(pix) * Cx;
- gg += G_VAL(pix) * Cx;
- bb += B_VAL(pix) * Cx;
- aa += A_VAL(pix) * Cx;
- }
- if(j > 0){
- pix++;
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- aa += A_VAL(pix) * j;
- }
- r = r * INV_YAP;
- g = g * INV_YAP;
- b = b * INV_YAP;
- a = a * INV_YAP;
- r = (r + ((rr * YAP))) >> 12;
- g = (g + ((gg * YAP))) >> 12;
- b = (b + ((bb * YAP))) >> 12;
- a = (a + ((aa * YAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- a >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 2) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally & vertically */
- else{
- /*\ 'Correct' version, with math units prepared for MMXification:
- |*| The operation 'b = (b * c) >> 16' translates to pmulhw,
- |*| so the operation 'b = (b * c) >> d' would translate to
- |*| psllw (16 - d), %mmb; pmulh %mmc, %mmb
- \*/
- int Cx, Cy, i, j;
- const unsigned int *pix;
- int a, r, g, b, ax, rx, gx, bx;
- int xap, yap;
-
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- sptr = ypoints[dyy + y] + xpoints[x];
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
-
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r = (rx >> 5) * yap;
- g = (gx >> 5) * yap;
- b = (bx >> 5) * yap;
- a = (ax >> 5) * yap;
-
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r += (rx >> 5) * Cy;
- g += (gx >> 5) * Cy;
- b += (bx >> 5) * Cy;
- a += (ax >> 5) * Cy;
- }
- if(j > 0){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r += (rx >> 5) * j;
- g += (gx >> 5) * j;
- b += (bx >> 5) * j;
- a += (ax >> 5) * j;
- }
-
- *dptr = qRgba(r >> 23, g >> 23, b >> 23, a >> 23);
- dptr++;
+ else {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+}
+
+inline static void qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b, int &a)
+{
+ r = R_VAL(pix) * xap;
+ g = G_VAL(pix) * xap;
+ b = B_VAL(pix) * xap;
+ a = A_VAL(pix) * xap;
+ int j;
+ for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
+ pix++;
+ r += R_VAL(pix) * Cx;
+ g += G_VAL(pix) * Cx;
+ b += B_VAL(pix) * Cx;
+ a += A_VAL(pix) * Cx;
+ }
+ pix++;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+ a += A_VAL(pix) * j;
+}
+
+inline static void qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b, int &a)
+{
+ r = R_VAL(pix) * yap;
+ g = G_VAL(pix) * yap;
+ b = B_VAL(pix) * yap;
+ a = A_VAL(pix) * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
+ pix += sow;
+ r += R_VAL(pix) * Cy;
+ g += G_VAL(pix) * Cy;
+ b += B_VAL(pix) * Cy;
+ a += A_VAL(pix) * Cy;
+ }
+ pix += sow;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+ a += A_VAL(pix) * j;
+}
+
+static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b, a;
+ qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, r, g, b, a);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ int rr, gg, bb, aa;
+ qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ a = a * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
+ a = (a + (aa * xap)) >> 8;
}
+ *dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
}
}
}
-/* scale by area sampling - IGNORE the ALPHA byte*/
-static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
{
- const unsigned int *sptr;
- unsigned int *dptr;
- int x, y, end;
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
- end = dxx + dw;
- /* scaling up both ways */
- if(isi->xup_yup == 3){
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- /* calculate the source line we'll scan from */
- dptr = dest + dx + ((y + dy) * dow);
- sptr = ypoints[dyy + y];
- if(YAP > 0){
- for(x = dxx; x < end; x++){
- int r = 0, g = 0, b = 0;
- int rr = 0, gg = 0, bb = 0;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- pix += sow;
- rr = R_VAL(pix) * XAP;
- gg = G_VAL(pix) * XAP;
- bb = B_VAL(pix) * XAP;
- pix --;
- rr += R_VAL(pix) * INV_XAP;
- gg += G_VAL(pix) * INV_XAP;
- bb += B_VAL(pix) * INV_XAP;
- r = ((rr * YAP) + (r * INV_YAP)) >> 16;
- g = ((gg * YAP) + (g * INV_YAP)) >> 16;
- b = ((bb * YAP) + (b * INV_YAP)) >> 16;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- else{
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_YAP;
- g = G_VAL(pix) * INV_YAP;
- b = B_VAL(pix) * INV_YAP;
- pix += sow;
- r += R_VAL(pix) * YAP;
- g += G_VAL(pix) * YAP;
- b += B_VAL(pix) * YAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- }
- }
- else{
- for(x = dxx; x < end; x++){
- int r = 0, g = 0, b = 0;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- else
- *dptr++ = sptr[xpoints[x] ];
- }
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b, a;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, r, g, b, a);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ int rr, gg, bb, aa;
+ qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, rr, gg, bb, aa);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ a = a * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ a = (a + (aa * yap)) >> 8;
}
+ *dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
+ dptr++;
}
}
- /* if we're scaling down vertically */
- else if(isi->xup_yup == 1){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cy, j;
- const unsigned int *pix;
- int r, g, b, rr, gg, bb;
- int yap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- pix += sow;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- pix += sow;
- }
- if(j > 0){
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- }
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + 1;
- rr = R_VAL(pix) * yap;
- gg = G_VAL(pix) * yap;
- bb = B_VAL(pix) * yap;
- pix += sow;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- rr += R_VAL(pix) * Cy;
- gg += G_VAL(pix) * Cy;
- bb += B_VAL(pix) * Cy;
- pix += sow;
- }
- if(j > 0){
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- }
- r = r * INV_XAP;
- g = g * INV_XAP;
- b = b * INV_XAP;
- r = (r + ((rr * XAP))) >> 12;
- g = (g + ((gg * XAP))) >> 12;
- b = (b + ((bb * XAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
- dptr++;
+}
+
+static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int rx, gx, bx, ax;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+
+ int r = ((rx>>4) * yap);
+ int g = ((gx>>4) * yap);
+ int b = ((bx>>4) * yap);
+ int a = ((ax>>4) * yap);
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+ r += ((rx>>4) * Cy);
+ g += ((gx>>4) * Cy);
+ b += ((bx>>4) * Cy);
+ a += ((ax>>4) * Cy);
}
+ sptr += sow;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+
+ r += ((rx>>4) * j);
+ g += ((gx>>4) * j);
+ b += ((bx>>4) * j);
+ a += ((ax>>4) * j);
+
+ *dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
+ dptr++;
}
}
+}
+
+static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+/* scale by area sampling - IGNORE the ALPHA byte*/
+static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ /* scaling up both ways */
+ if (isi->xup_yup == 3) {
+ qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+ /* if we're scaling down vertically */
+ else if (isi->xup_yup == 1) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
/* if we're scaling down horizontally */
- else if(isi->xup_yup == 2){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, j;
- const unsigned int *pix;
- int r, g, b, rr, gg, bb;
- int xap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
- pix++;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- pix++;
- }
- if(j > 0){
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- }
- if(YAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + sow;
- rr = R_VAL(pix) * xap;
- gg = G_VAL(pix) * xap;
- bb = B_VAL(pix) * xap;
- pix++;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- rr += R_VAL(pix) * Cx;
- gg += G_VAL(pix) * Cx;
- bb += B_VAL(pix) * Cx;
- pix++;
- }
- if(j > 0){
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- }
- r = r * INV_YAP;
- g = g * INV_YAP;
- b = b * INV_YAP;
- r = (r + ((rr * YAP))) >> 12;
- g = (g + ((gg * YAP))) >> 12;
- b = (b + ((bb * YAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 2) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
- /* fully optimized (i think) - onyl change of algorithm can help */
/* if we're scaling down horizontally & vertically */
- else{
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, Cy, i, j;
- const unsigned int *pix;
- int r, g, b, rx, gx, bx;
- int xap, yap;
-
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- sptr = ypoints[dyy + y] + xpoints[x];
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r = (rx >> 5) * yap;
- g = (gx >> 5) * yap;
- b = (bx >> 5) * yap;
-
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r += (rx >> 5) * Cy;
- g += (gx >> 5) * Cy;
- b += (bx >> 5) * Cy;
- }
- if(j > 0){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r += (rx >> 5) * j;
- g += (gx >> 5) * j;
- b += (bx >> 5) * j;
- }
-
- *dptr = qRgb(r >> 23, g >> 23, b >> 23);
- dptr++;
+ else {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+}
+
+
+inline static void qt_qimageScaleAARGB_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b)
+{
+ r = R_VAL(pix) * xap;
+ g = G_VAL(pix) * xap;
+ b = B_VAL(pix) * xap;
+ int j;
+ for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
+ pix++;
+ r += R_VAL(pix) * Cx;
+ g += G_VAL(pix) * Cx;
+ b += B_VAL(pix) * Cx;
+ }
+ pix++;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+}
+
+inline static void qt_qimageScaleAARGB_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b)
+{
+ r = R_VAL(pix) * yap;
+ g = G_VAL(pix) * yap;
+ b = B_VAL(pix) * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
+ pix += sow;
+ r += R_VAL(pix) * Cy;
+ g += G_VAL(pix) * Cy;
+ b += B_VAL(pix) * Cy;
+ }
+ pix += sow;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+}
+
+static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b;
+ qt_qimageScaleAARGB_helper_y(sptr, yap, Cy, sow, r, g, b);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ int rr, bb, gg;
+ qt_qimageScaleAARGB_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
}
+ *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
}
}
}
-#if 0
-static void qt_qimageScaleAARGBASetup(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
{
- qInitDrawhelperAsm();
- qt_qimageScaleAARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, r, g, b);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ int rr, bb, gg;
+ qt_qimageScaleAARGB_helper_x(sptr + sow, xap, Cx, rr, gg, bb);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ }
+ *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
+ }
+ }
}
-static void qt_qimageScaleAARGBSetup(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
{
- qInitDrawhelperAsm();
- qt_qimageScaleAARGB(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int rx, gx, bx;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ int r = (rx >> 4) * yap;
+ int g = (gx >> 4) * yap;
+ int b = (bx >> 4) * yap;
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ r += (rx >> 4) * Cy;
+ g += (gx >> 4) * Cy;
+ b += (bx >> 4) * Cy;
+ }
+ sptr += sow;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ r += (rx >> 4) * j;
+ g += (gx >> 4) * j;
+ b += (bx >> 4) * j;
+
+ *dptr = qRgb(r >> 24, g >> 24, b >> 24);
+ dptr++;
+ }
+ }
}
-#endif
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
{
@@ -1012,7 +793,7 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
- if (src.format() == QImage::Format_ARGB32_Premultiplied || src.format() == QImage::Format_RGBA8888_Premultiplied)
+ if (src.hasAlphaChannel())
qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qimagescale_p.h b/src/gui/painting/qimagescale_p.h
index 512ec6488e..c35aea451a 100644
--- a/src/gui/painting/qimagescale_p.h
+++ b/src/gui/painting/qimagescale_p.h
@@ -53,6 +53,15 @@ QT_BEGIN_NAMESPACE
*/
QImage qSmoothScaleImage(const QImage &img, int w, int h);
+namespace QImageScale {
+ struct QImageScaleInfo {
+ int *xpoints;
+ const unsigned int **ypoints;
+ int *xapoints, *yapoints;
+ int xup_yup;
+ };
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
new file mode 100644
index 0000000000..565ea4daa1
--- /dev/null
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qimagescale_p.h"
+#include "qimage.h"
+#include <private/qsimd_p.h>
+
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
+
+QT_BEGIN_NAMESPACE
+
+using namespace QImageScale;
+
+inline static __m128i qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, const __m128i vxap, const __m128i vCx)
+{
+ __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ __m128i vx = _mm_mullo_epi32(vpix, vxap);
+ int i;
+ for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
+ pix++;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCx));
+ }
+ pix++;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
+ return vx;
+}
+
+inline static __m128i qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, const __m128i vyap, const __m128i vCy)
+{
+ __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ __m128i vx = _mm_mullo_epi32(vpix, vyap);
+ int i;
+ for (i = (1 << 14) - yap; i > Cy; i -= Cy) {
+ pix += sow;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCy));
+ }
+ pix += sow;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
+ return vx;
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ const __m128i v256 = _mm_set1_epi32(256);
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+ const __m128i vCy = _mm_set1_epi32(Cy);
+ const __m128i vyap = _mm_set1_epi32(yap);
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, vyap, vCy);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ const __m128i vxap = _mm_set1_epi32(xap);
+ const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
+ __m128i vr = qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, vyap, vCy);
+
+ vx = _mm_mullo_epi32(vx, vinvxap);
+ vr = _mm_mullo_epi32(vr, vxap);
+ vx = _mm_add_epi32(vx, vr);
+ vx = _mm_srli_epi32(vx, 8);
+ }
+ vx = _mm_srli_epi32(vx, 14);
+ vx = _mm_packus_epi32(vx, _mm_setzero_si128());
+ vx = _mm_packus_epi16(vx, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vx);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ const __m128i v256 = _mm_set1_epi32(256);
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+ const __m128i vCx = _mm_set1_epi32(Cx);
+ const __m128i vxap = _mm_set1_epi32(xap);
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ const __m128i vyap = _mm_set1_epi32(yap);
+ const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
+ __m128i vr = qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, vxap, vCx);
+
+ vx = _mm_mullo_epi32(vx, vinvyap);
+ vr = _mm_mullo_epi32(vr, vyap);
+ vx = _mm_add_epi32(vx, vr);
+ vx = _mm_srli_epi32(vx, 8);
+ }
+ vx = _mm_srli_epi32(vx, 14);
+ vx = _mm_packus_epi32(vx, _mm_setzero_si128());
+ vx = _mm_packus_epi16(vx, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vx);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+ const __m128i vCy = _mm_set1_epi32(Cy);
+ const __m128i vyap = _mm_set1_epi32(yap);
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ int end = dxx + dw;
+ for (int x = dxx; x < end; x++) {
+ const int Cx = xapoints[x] >> 16;
+ const int xap = xapoints[x] & 0xffff;
+ const __m128i vCx = _mm_set1_epi32(Cx);
+ const __m128i vxap = _mm_set1_epi32(xap);
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ __m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy));
+ }
+ sptr += sow;
+ vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
+
+ vr = _mm_srli_epi32(vr, 24);
+ vr = _mm_packus_epi32(vr, _mm_setzero_si128());
+ vr = _mm_packus_epi16(vr, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vr);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template void qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_xy_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_xy_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index acedc6a7ba..e4d756c18d 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -31,9 +31,11 @@
**
****************************************************************************/
+#include "qmatrix.h"
+
#include "qdatastream.h"
#include "qdebug.h"
-#include "qmatrix.h"
+#include "qhashfunctions.h"
#include "qregion.h"
#include "qpainterpath.h"
#include "qpainterpath_p.h"
@@ -972,6 +974,26 @@ bool QMatrix::operator==(const QMatrix &m) const
_dy == m._dy;
}
+
+/*!
+ \since 5.6
+ \relates QMatrix
+
+ Returns the hash value for \a key, using
+ \a seed to seed the calculation.
+*/
+uint qHash(const QMatrix &key, uint seed) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(key.m11(), seed);
+ seed = hash(key.m12(), seed);
+ seed = hash(key.m21(), seed);
+ seed = hash(key.m22(), seed);
+ seed = hash(key.dx(), seed);
+ seed = hash(key.dy(), seed);
+ return seed;
+}
+
/*!
\fn bool QMatrix::operator!=(const QMatrix &matrix) const
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index ddffa8a8b9..c036e4df93 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -126,6 +126,8 @@ private:
};
Q_DECLARE_TYPEINFO(QMatrix, Q_MOVABLE_TYPE);
+Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QMatrix &key, uint seed = 0) Q_DECL_NOTHROW;
+
// mathematical semantics
inline QPoint operator*(const QPoint &p, const QMatrix &m)
{ return m.map(p); }
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 3be6e0f1f4..882a088d5c 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -42,7 +42,6 @@
#include <qpainterpath.h>
#include <qdebug.h>
-#include <qhash.h>
#include <qbitmap.h>
#include <qmath.h>
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index fdad8e2460..e8b675365f 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -53,7 +53,6 @@
#include "QtGui/qpainter.h"
#include "QtGui/qpainterpath.h"
#include "QtGui/qpaintengine.h"
-#include <QtCore/qhash.h>
#include <private/qpen_p.h>
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index ebb0e5f142..9b1f5e334a 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -66,12 +66,9 @@ QT_BEGIN_NAMESPACE
inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
{
QPaintEngine::PaintEngineFeatures f = QPaintEngine::AllFeatures;
- f &= ~(QPaintEngine::PorterDuff | QPaintEngine::PerspectiveTransform
+ f &= ~(QPaintEngine::PorterDuff
+ | QPaintEngine::PerspectiveTransform
| QPaintEngine::ObjectBoundingModeGradients
-#ifndef USE_NATIVE_GRADIENTS
- | QPaintEngine::LinearGradientFill
-#endif
- | QPaintEngine::RadialGradientFill
| QPaintEngine::ConicalGradientFill);
return f;
}
@@ -548,189 +545,6 @@ QByteArray QPdf::patternForBrush(const QBrush &b)
return pattern_for_brush[style];
}
-#ifdef USE_NATIVE_GRADIENTS
-static void writeTriangleLine(uchar *&data, int xpos, int ypos, int xoff, int yoff, uint rgb, uchar flag, bool alpha)
-{
- data[0] = flag;
- data[1] = (uchar)(xpos >> 16);
- data[2] = (uchar)(xpos >> 8);
- data[3] = (uchar)(xpos >> 0);
- data[4] = (uchar)(ypos >> 16);
- data[5] = (uchar)(ypos >> 8);
- data[6] = (uchar)(ypos >> 0);
- data += 7;
- if (alpha) {
- *data++ = (uchar)qAlpha(rgb);
- } else {
- *data++ = (uchar)qRed(rgb);
- *data++ = (uchar)qGreen(rgb);
- *data++ = (uchar)qBlue(rgb);
- }
- xpos += xoff;
- ypos += yoff;
- data[0] = flag;
- data[1] = (uchar)(xpos >> 16);
- data[2] = (uchar)(xpos >> 8);
- data[3] = (uchar)(xpos >> 0);
- data[4] = (uchar)(ypos >> 16);
- data[5] = (uchar)(ypos >> 8);
- data[6] = (uchar)(ypos >> 0);
- data += 7;
- if (alpha) {
- *data++ = (uchar)qAlpha(rgb);
- } else {
- *data++ = (uchar)qRed(rgb);
- *data++ = (uchar)qGreen(rgb);
- *data++ = (uchar)qBlue(rgb);
- }
-}
-
-
-QByteArray QPdf::generateLinearGradientShader(const QLinearGradient *gradient, const QPointF *page_rect, bool alpha)
-{
- // generate list of triangles with colors
- QPointF start = gradient->start();
- QPointF stop = gradient->finalStop();
- QGradientStops stops = gradient->stops();
- QPointF offset = stop - start;
- QGradient::Spread spread = gradient->spread();
-
- if (gradient->spread() == QGradient::ReflectSpread) {
- offset *= 2;
- for (int i = stops.size() - 2; i >= 0; --i) {
- QGradientStop stop = stops.at(i);
- stop.first = 2. - stop.first;
- stops.append(stop);
- }
- for (int i = 0 ; i < stops.size(); ++i)
- stops[i].first /= 2.;
- }
-
- QPointF orthogonal(offset.y(), -offset.x());
- qreal length = offset.x()*offset.x() + offset.y()*offset.y();
-
- // find the max and min values in offset and orth direction that are needed to cover
- // the whole page
- int off_min = INT_MAX;
- int off_max = INT_MIN;
- qreal ort_min = INT_MAX;
- qreal ort_max = INT_MIN;
- for (int i = 0; i < 4; ++i) {
- qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length;
- qreal ort = ((page_rect[i].x() - start.x()) * orthogonal.x() + (page_rect[i].y() - start.y()) * orthogonal.y())/length;
- off_min = qMin(off_min, qFloor(off));
- off_max = qMax(off_max, qCeil(off));
- ort_min = qMin(ort_min, ort);
- ort_max = qMax(ort_max, ort);
- }
- ort_min -= 1;
- ort_max += 1;
-
- start += off_min * offset + ort_min * orthogonal;
- orthogonal *= (ort_max - ort_min);
- int num = off_max - off_min;
-
- QPointF gradient_rect[4] = { start,
- start + orthogonal,
- start + num*offset,
- start + num*offset + orthogonal };
- qreal xmin = gradient_rect[0].x();
- qreal xmax = gradient_rect[0].x();
- qreal ymin = gradient_rect[0].y();
- qreal ymax = gradient_rect[0].y();
- for (int i = 1; i < 4; ++i) {
- xmin = qMin(xmin, gradient_rect[i].x());
- xmax = qMax(xmax, gradient_rect[i].x());
- ymin = qMin(ymin, gradient_rect[i].y());
- ymax = qMax(ymax, gradient_rect[i].y());
- }
- xmin -= 1000;
- xmax += 1000;
- ymin -= 1000;
- ymax += 1000;
- start -= QPointF(xmin, ymin);
- qreal factor_x = qreal(1<<24)/(xmax - xmin);
- qreal factor_y = qreal(1<<24)/(ymax - ymin);
- int xoff = (int)(orthogonal.x()*factor_x);
- int yoff = (int)(orthogonal.y()*factor_y);
-
- QByteArray triangles;
- triangles.resize(spread == QGradient::PadSpread ? 20*(stops.size()+2) : 20*num*stops.size());
- uchar *data = (uchar *) triangles.data();
- if (spread == QGradient::PadSpread) {
- if (off_min > 0 || off_max < 1) {
- // linear gradient outside of page
- const QGradientStop &current_stop = off_min > 0 ? stops.at(stops.size()-1) : stops.at(0);
- uint rgb = current_stop.second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 0, alpha);
- start += num*offset;
- xpos = (int)(start.x()*factor_x);
- ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 1, alpha);
- } else {
- int flag = 0;
- if (off_min < 0) {
- uint rgb = stops.at(0).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- start -= off_min*offset;
- flag = 1;
- }
- for (int s = 0; s < stops.size(); ++s) {
- const QGradientStop &current_stop = stops.at(s);
- uint rgb = current_stop.second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- if (s < stops.size()-1)
- start += offset*(stops.at(s+1).first - stops.at(s).first);
- flag = 1;
- }
- if (off_max > 1) {
- start += (off_max - 1)*offset;
- uint rgb = stops.at(stops.size()-1).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- }
- }
- } else {
- for (int i = 0; i < num; ++i) {
- uchar flag = 0;
- for (int s = 0; s < stops.size(); ++s) {
- uint rgb = stops.at(s).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- if (s < stops.size()-1)
- start += offset*(stops.at(s+1).first - stops.at(s).first);
- flag = 1;
- }
- }
- }
- triangles.resize((char *)data - triangles.constData());
-
- QByteArray shader;
- QPdf::ByteStream s(&shader);
- s << "<<\n"
- "/ShadingType 4\n"
- "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
- "/AntiAlias true\n"
- "/BitsPerCoordinate 24\n"
- "/BitsPerComponent 8\n"
- "/BitsPerFlag 8\n"
- "/Decode [" << xmin << xmax << ymin << ymax << (alpha ? "0 1]\n" : "0 1 0 1 0 1]\n") <<
- "/AntiAlias true\n"
- "/Length " << triangles.length() << "\n"
- ">>\n"
- "stream\n" << triangles << "endstream\n"
- "endobj\n";
- return shader;
-}
-#endif
static void moveToHook(qfixed x, qfixed y, void *data)
{
@@ -1381,6 +1195,8 @@ void QPdfEngine::setBrush()
bool specifyColor;
int gStateObject = 0;
int patternObject = d->addBrushPattern(d->stroker.matrix, &specifyColor, &gStateObject);
+ if (!patternObject && !specifyColor)
+ return;
*d->currentPage << (patternObject ? "/PCSp cs " : "/CSp cs ");
if (specifyColor) {
@@ -2119,34 +1935,263 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
return image;
}
-#ifdef USE_NATIVE_GRADIENTS
-int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject)
+struct QGradientBound {
+ qreal start;
+ qreal stop;
+ int function;
+ bool reverse;
+};
+
+int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
{
- const QGradient *gradient = b.gradient();
- if (!gradient)
- return 0;
+ QGradientStops stops = gradient->stops();
+ if (stops.isEmpty()) {
+ stops << QGradientStop(0, Qt::black);
+ stops << QGradientStop(1, Qt::white);
+ }
+ if (stops.at(0).first > 0)
+ stops.prepend(QGradientStop(0, stops.at(0).second));
+ if (stops.at(stops.size() - 1).first < 1)
+ stops.append(QGradientStop(1, stops.at(stops.size() - 1).second));
+
+ QVector<int> functions;
+ for (int i = 0; i < stops.size() - 1; ++i) {
+ int f = addXrefEntry(-1);
+ QByteArray data;
+ QPdf::ByteStream s(&data);
+ s << "<<\n"
+ "/FunctionType 2\n"
+ "/Domain [0 1]\n"
+ "/N 1\n";
+ if (alpha) {
+ s << "/C0 [" << stops.at(i).second.alphaF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.alphaF() << "]\n";
+ } else {
+ s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
+ }
+ s << ">>\n"
+ "endobj\n";
+ write(data);
+ functions << f;
+ }
+
+ QVector<QGradientBound> gradientBounds;
- QTransform inv = matrix.inverted();
- QPointF page_rect[4] = { inv.map(QPointF(0, 0)),
- inv.map(QPointF(width_, 0)),
- inv.map(QPointF(0, height_)),
- inv.map(QPointF(width_, height_)) };
+ for (int step = from; step < to; ++step) {
+ if (reflect && step % 2) {
+ for (int i = stops.size() - 1; i > 0; --i) {
+ QGradientBound b;
+ b.start = step + 1 - qBound(0., stops.at(i).first, 1.);
+ b.stop = step + 1 - qBound(0., stops.at(i - 1).first, 1.);
+ b.function = functions.at(i - 1);
+ b.reverse = true;
+ gradientBounds << b;
+ }
+ } else {
+ for (int i = 0; i < stops.size() - 1; ++i) {
+ QGradientBound b;
+ b.start = step + qBound(0., stops.at(i).first, 1.);
+ b.stop = step + qBound(0., stops.at(i + 1).first, 1.);
+ b.function = functions.at(i);
+ b.reverse = false;
+ gradientBounds << b;
+ }
+ }
+ }
- bool opaque = b.isOpaque();
+ // normalize bounds to [0..1]
+ qreal bstart = gradientBounds.at(0).start;
+ qreal bend = gradientBounds.at(gradientBounds.size() - 1).stop;
+ qreal norm = 1./(bend - bstart);
+ for (int i = 0; i < gradientBounds.size(); ++i) {
+ gradientBounds[i].start = (gradientBounds[i].start - bstart)*norm;
+ gradientBounds[i].stop = (gradientBounds[i].stop - bstart)*norm;
+ }
- QByteArray shader;
- QByteArray alphaShader;
- if (gradient->type() == QGradient::LinearGradient) {
- const QLinearGradient *lg = static_cast<const QLinearGradient *>(gradient);
- shader = QPdf::generateLinearGradientShader(lg, page_rect);
- if (!opaque)
- alphaShader = QPdf::generateLinearGradientShader(lg, page_rect, true);
+ int function;
+ if (gradientBounds.size() > 1) {
+ function = addXrefEntry(-1);
+ QByteArray data;
+ QPdf::ByteStream s(&data);
+ s << "<<\n"
+ "/FunctionType 3\n"
+ "/Domain [0 1]\n"
+ "/Bounds [";
+ for (int i = 1; i < gradientBounds.size(); ++i)
+ s << gradientBounds.at(i).start;
+ s << "]\n"
+ "/Encode [";
+ for (int i = 0; i < gradientBounds.size(); ++i)
+ s << (gradientBounds.at(i).reverse ? "1 0 " : "0 1 ");
+ s << "]\n"
+ "/Functions [";
+ for (int i = 0; i < gradientBounds.size(); ++i)
+ s << gradientBounds.at(i).function << "0 R ";
+ s << "]\n"
+ ">>\n";
+ write(data);
} else {
- // #############
- return 0;
+ function = functions.at(0);
+ }
+ return function;
+}
+
+int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ QPointF start = gradient->start();
+ QPointF stop = gradient->finalStop();
+ QPointF offset = stop - start;
+ Q_ASSERT(gradient->coordinateMode() == QGradient::LogicalMode);
+
+ int from = 0;
+ int to = 1;
+ bool reflect = false;
+ switch (gradient->spread()) {
+ case QGradient::PadSpread:
+ break;
+ case QGradient::ReflectSpread:
+ reflect = true;
+ // fall through
+ case QGradient::RepeatSpread: {
+ // calculate required bounds
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+ QTransform inv = matrix.inverted();
+ QPointF page_rect[4] = { inv.map(pageRect.topLeft()),
+ inv.map(pageRect.topRight()),
+ inv.map(pageRect.bottomLeft()),
+ inv.map(pageRect.bottomRight()) };
+
+ qreal length = offset.x()*offset.x() + offset.y()*offset.y();
+
+ // find the max and min values in offset and orth direction that are needed to cover
+ // the whole page
+ from = INT_MAX;
+ to = INT_MIN;
+ for (int i = 0; i < 4; ++i) {
+ qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length;
+ from = qMin(from, qFloor(off));
+ to = qMax(to, qCeil(off));
+ }
+
+ stop = start + to * offset;
+ start = start + from * offset;\
+ break;
+ }
+ }
+
+ int function = createShadingFunction(gradient, from, to, reflect, alpha);
+
+ QByteArray shader;
+ QPdf::ByteStream s(&shader);
+ s << "<<\n"
+ "/ShadingType 2\n"
+ "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
+ "/AntiAlias true\n"
+ "/Coords [" << start.x() << start.y() << stop.x() << stop.y() << "]\n"
+ "/Extend [true true]\n"
+ "/Function " << function << "0 R\n"
+ ">>\n"
+ "endobj\n";
+ int shaderObject = addXrefEntry(-1);
+ write(shader);
+ return shaderObject;
+}
+
+int QPdfEnginePrivate::generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ QPointF p1 = gradient->center();
+ double r1 = gradient->centerRadius();
+ QPointF p0 = gradient->focalPoint();
+ double r0 = gradient->focalRadius();
+
+ Q_ASSERT(gradient->coordinateMode() == QGradient::LogicalMode);
+
+ int from = 0;
+ int to = 1;
+ bool reflect = false;
+ switch (gradient->spread()) {
+ case QGradient::PadSpread:
+ break;
+ case QGradient::ReflectSpread:
+ reflect = true;
+ // fall through
+ case QGradient::RepeatSpread: {
+ Q_ASSERT(qFuzzyIsNull(r0)); // QPainter emulates if this is not 0
+
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+ QTransform inv = matrix.inverted();
+ QPointF page_rect[4] = { inv.map(pageRect.topLeft()),
+ inv.map(pageRect.topRight()),
+ inv.map(pageRect.bottomLeft()),
+ inv.map(pageRect.bottomRight()) };
+
+ // increase to until the whole page fits into it
+ bool done = false;
+ while (!done) {
+ QPointF center = QPointF(p0.x() + to*(p1.x() - p0.x()), p0.y() + to*(p1.y() - p0.y()));
+ double radius = r0 + to*(r1 - r0);
+ double r2 = radius*radius;
+ done = true;
+ for (int i = 0; i < 4; ++i) {
+ QPointF off = page_rect[i] - center;
+ if (off.x()*off.x() + off.y()*off.y() > r2) {
+ ++to;
+ done = false;
+ break;
+ }
+ }
+ }
+ p1 = QPointF(p0.x() + to*(p1.x() - p0.x()), p0.y() + to*(p1.y() - p0.y()));
+ r1 = r0 + to*(r1 - r0);
+ break;
+ }
}
+
+ int function = createShadingFunction(gradient, from, to, reflect, alpha);
+
+ QByteArray shader;
+ QPdf::ByteStream s(&shader);
+ s << "<<\n"
+ "/ShadingType 3\n"
+ "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
+ "/AntiAlias true\n"
+ "/Domain [0 1]\n"
+ "/Coords [" << p0.x() << p0.y() << r0 << p1.x() << p1.y() << r1 << "]\n"
+ "/Extend [true true]\n"
+ "/Function " << function << "0 R\n"
+ ">>\n"
+ "endobj\n";
int shaderObject = addXrefEntry(-1);
write(shader);
+ return shaderObject;
+}
+
+int QPdfEnginePrivate::generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ switch (gradient->type()) {
+ case QGradient::LinearGradient:
+ return generateLinearGradientShader(static_cast<const QLinearGradient *>(gradient), matrix, alpha);
+ case QGradient::RadialGradient:
+ return generateRadialGradientShader(static_cast<const QRadialGradient *>(gradient), matrix, alpha);
+ case QGradient::ConicalGradient:
+ default:
+ qWarning() << "Implement me!";
+ }
+ return 0;
+}
+
+int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QTransform &matrix, int *gStateObject)
+{
+ const QGradient *gradient = b.gradient();
+
+ if (!gradient || gradient->coordinateMode() != QGradient::LogicalMode)
+ return 0;
+
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+
+ QTransform m = b.transform() * matrix;
+ int shaderObject = generateGradientShader(gradient, m);
QByteArray str;
QPdf::ByteStream s(&str);
@@ -2155,12 +2200,12 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
"/PatternType 2\n"
"/Shading " << shaderObject << "0 R\n"
"/Matrix ["
- << matrix.m11()
- << matrix.m12()
- << matrix.m21()
- << matrix.m22()
- << matrix.dx()
- << matrix.dy() << "]\n";
+ << m.m11()
+ << m.m12()
+ << m.m21()
+ << m.m22()
+ << m.dx()
+ << m.dy() << "]\n";
s << ">>\n"
"endobj\n";
@@ -2168,7 +2213,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
write(str);
currentPage->patterns.append(patternObj);
- if (!opaque) {
+ if (!b.isOpaque()) {
bool ca = true;
QGradientStops stops = gradient->stops();
int a = stops.at(0).second.alpha();
@@ -2181,8 +2226,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
if (ca) {
*gStateObject = addConstantAlphaObject(stops.at(0).second.alpha());
} else {
- int alphaShaderObject = addXrefEntry(-1);
- write(alphaShader);
+ int alphaShaderObject = generateGradientShader(gradient, m, true);
QByteArray content;
QPdf::ByteStream c(&content);
@@ -2193,7 +2237,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
f << "<<\n"
"/Type /XObject\n"
"/Subtype /Form\n"
- "/BBox [0 0 " << width_ << height_ << "]\n"
+ "/BBox [0 0 " << pageRect.width() << pageRect.height() << "]\n"
"/Group <</S /Transparency >>\n"
"/Resources <<\n"
"/Shading << /Shader" << alphaShaderObject << alphaShaderObject << "0 R >>\n"
@@ -2217,7 +2261,6 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
return patternObj;
}
-#endif
int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
{
@@ -2239,6 +2282,7 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
return object;
}
+
int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject)
{
int paintType = 2; // Uncolored tiling
@@ -2254,13 +2298,9 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
//qDebug() << brushOrigin << matrix;
Qt::BrushStyle style = brush.style();
- if (style == Qt::LinearGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
-#ifdef USE_NATIVE_GRADIENTS
+ if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
*specifyColor = false;
- return gradientBrush(b, matrix, gStateObject);
-#else
- return 0;
-#endif
+ return gradientBrush(brush, matrix, gStateObject);
}
if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index e7ff09cd3b..94e74f30b9 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -58,8 +58,6 @@
#include "private/qfontsubset_p.h"
#include "qpagelayout.h"
-// #define USE_NATIVE_GRADIENTS
-
QT_BEGIN_NAMESPACE
const char *qt_real_to_string(qreal val, char *buf);
@@ -116,9 +114,6 @@ namespace QPdf {
QByteArray generateMatrix(const QTransform &matrix);
QByteArray generateDashes(const QPen &pen);
QByteArray patternForBrush(const QBrush &b);
-#ifdef USE_NATIVE_GRADIENTS
- QByteArray generateLinearGradientShader(const QLinearGradient *lg, const QPointF *page_rect, bool alpha = false);
-#endif
struct Stroker {
Stroker();
@@ -276,9 +271,11 @@ public:
QPageLayout m_pageLayout;
private:
-#ifdef USE_NATIVE_GRADIENTS
- int gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject);
-#endif
+ int gradientBrush(const QBrush &b, const QTransform &matrix, int *gStateObject);
+ int generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha = false);
+ int generateLinearGradientShader(const QLinearGradient *lg, const QTransform &matrix, bool alpha);
+ int generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha);
+ int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
void writeInfo();
void writePageRoot();
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index 51ce4ab10d..290501047d 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -40,13 +40,15 @@
QT_BEGIN_NAMESPACE
class QRgba64 {
+ struct qrgba_t {
+ quint16 red;
+ quint16 green;
+ quint16 blue;
+ quint16 alpha;
+ };
+
union {
- struct {
- quint16 red;
- quint16 green;
- quint16 blue;
- quint16 alpha;
- } c;
+ struct qrgba_t c;
quint64 rgba;
};
public:
@@ -167,6 +169,8 @@ private:
}
};
+Q_DECLARE_TYPEINFO(QRgba64, Q_PRIMITIVE_TYPE);
+
Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
{
return QRgba64::fromRgba64(r, g, b, a);
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index a1452af8d9..c6cbe666ac 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -36,6 +36,7 @@
#include <QtGui/qrgba64.h>
#include <QtGui/private/qdrawhelper_p.h>
+#include <private/qsimd_p.h>
QT_BEGIN_NAMESPACE
@@ -52,20 +53,36 @@ inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256)
(rgba64.alpha() * alpha256) >> 8);
}
-inline QRgba64 multiplyAlpha255(QRgba64 rgba64, uint alpha255)
-{
- return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255),
- qt_div_255(rgba64.green() * alpha255),
- qt_div_255(rgba64.blue() * alpha255),
- qt_div_255(rgba64.alpha() * alpha255));
-}
-
inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535)
{
+#ifdef __SSE2__
+ const __m128i va = _mm_shufflelo_epi16(_mm_cvtsi32_si128(alpha65535), _MM_SHUFFLE(0, 0, 0, 0));
+ __m128i vs = _mm_loadl_epi64((__m128i*)&rgba64);
+ vs = _mm_unpacklo_epi16(_mm_mullo_epi16(vs, va), _mm_mulhi_epu16(vs, va));
+ vs = _mm_add_epi32(vs, _mm_srli_epi32(vs, 16));
+ vs = _mm_add_epi32(vs, _mm_set1_epi32(0x8000));
+ vs = _mm_srai_epi32(vs, 16);
+ vs = _mm_packs_epi32(vs, _mm_setzero_si128());
+ _mm_storel_epi64((__m128i*)&rgba64, vs);
+ return rgba64;
+#else
return QRgba64::fromRgba64(qt_div_65535(rgba64.red() * alpha65535),
qt_div_65535(rgba64.green() * alpha65535),
qt_div_65535(rgba64.blue() * alpha65535),
qt_div_65535(rgba64.alpha() * alpha65535));
+#endif
+}
+
+inline QRgba64 multiplyAlpha255(QRgba64 rgba64, uint alpha255)
+{
+#ifdef __SSE2__
+ return multiplyAlpha65535(rgba64, alpha255 * 257);
+#else
+ return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255),
+ qt_div_255(rgba64.green() * alpha255),
+ qt_div_255(rgba64.blue() * alpha255),
+ qt_div_255(rgba64.alpha() * alpha255));
+#endif
}
inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
@@ -78,6 +95,26 @@ inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2));
}
+inline QRgba64 interpolate65535(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
+{
+ return QRgba64::fromRgba64(multiplyAlpha65535(x, alpha1) + multiplyAlpha65535(y, alpha2));
+}
+
+inline QRgba64 addWithSaturation(QRgba64 a, QRgba64 b)
+{
+#if defined(__SSE2__) && defined(Q_PROCESSOR_X86_64)
+ __m128i va = _mm_cvtsi64_si128((quint64)a);
+ __m128i vb = _mm_cvtsi64_si128((quint64)b);
+ va = _mm_adds_epu16(va, vb);
+ return QRgba64::fromRgba64(_mm_cvtsi128_si64(va));
+#else
+ return QRgba64::fromRgba64(qMin(a.red() + b.red(), 65535),
+ qMin(a.green() + b.green(), 65535),
+ qMin(a.blue() + b.blue(), 65535),
+ qMin(a.alpha() + b.alpha(), 65535));
+#endif
+}
+
QT_END_NAMESPACE
#endif // QRGBA64_P_H
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 31d7a2300b..4b3f0b30dc 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -34,6 +34,7 @@
#include "qdatastream.h"
#include "qdebug.h"
+#include "qhashfunctions.h"
#include "qmatrix.h"
#include "qregion.h"
#include "qpainterpath.h"
@@ -776,6 +777,29 @@ bool QTransform::operator==(const QTransform &o) const
}
/*!
+ \since 5.6
+ \relates QTransform
+
+ Returns the hash value for \a key, using
+ \a seed to seed the calculation.
+*/
+uint qHash(const QTransform &key, uint seed) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(key.m11(), seed);
+ seed = hash(key.m12(), seed);
+ seed = hash(key.m21(), seed);
+ seed = hash(key.m22(), seed);
+ seed = hash(key.dx(), seed);
+ seed = hash(key.dy(), seed);
+ seed = hash(key.m13(), seed);
+ seed = hash(key.m23(), seed);
+ seed = hash(key.m33(), seed);
+ return seed;
+}
+
+
+/*!
\fn bool QTransform::operator!=(const QTransform &matrix) const
Returns \c true if this matrix is not equal to the given \a matrix,
otherwise returns \c false.
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index cf8d4d1970..65f543144d 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -180,6 +180,8 @@ private:
};
Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE);
+Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) Q_DECL_NOTHROW;
+
/******* inlines *****/
inline QTransform::TransformationType QTransform::inline_type() const
{