diff options
author | Morten Johan Sørvig <morten.sorvig@digia.com> | 2015-04-13 14:28:58 +0200 |
---|---|---|
committer | Morten Johan Sørvig <morten.sorvig@digia.com> | 2015-04-13 14:28:58 +0200 |
commit | 02ff2973ceeef00ced4468b6e15cfadd9f021b0d (patch) | |
tree | e5b51329fceb3d0134e533e41c0f3800549f1786 /src/gui/painting | |
parent | c5b743472fc36986cf34636dbcb73a0d0fa6b9e6 (diff) | |
parent | 16c32710bc8a5ecefc833352159361be564f3fe4 (diff) |
Merge remote-tracking branch 'gerrit/dev' into dev-highdpi
Conflicts:
src/plugins/platforms/xcb/qxcbbackingstore.cpp
Change-Id: Ib7f277957636186d0abd58d8c710392ef7b02e13
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/painting.pri | 1 | ||||
-rw-r--r-- | src/gui/painting/qbrush.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qcolor.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qcosmeticstroker.cpp | 23 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 909 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 5 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 106 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_sse2.cpp | 17 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_x86_p.h | 6 | ||||
-rw-r--r-- | src/gui/painting/qmatrix.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qpagelayout.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qpagesize.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 101 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qpen.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qpolygon.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/qrgba64.h | 9 | ||||
-rw-r--r-- | src/gui/painting/qrgba64_p.h | 83 | ||||
-rw-r--r-- | src/gui/painting/qtextureglyphcache.cpp | 11 | ||||
-rw-r--r-- | src/gui/painting/qtransform.cpp | 3 |
21 files changed, 1012 insertions, 290 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 3010d4052a..fafc67cf46 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -44,6 +44,7 @@ HEADERS += \ painting/qregion.h \ painting/qrgb.h \ painting/qrgba64.h \ + painting/qrgba64_p.h \ painting/qstroker_p.h \ painting/qtextureglyphcache_p.h \ painting/qtransform.h \ diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 27f28f7193..5bf8387400 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -1022,8 +1022,9 @@ QDebug operator<<(QDebug dbg, const QBrush &b) "TexturePattern" // 24 }; + QDebugStateSaver saver(dbg); dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')'; - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 806c9362ac..b33d7a74fc 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -2469,6 +2469,7 @@ void QColor::invalidate() #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QColor &c) { + QDebugStateSaver saver(dbg); if (!c.isValid()) dbg.nospace() << "QColor(Invalid)"; else if (c.spec() == QColor::Rgb) @@ -2481,7 +2482,7 @@ QDebug operator<<(QDebug dbg, const QColor &c) else if (c.spec() == QColor::Hsl) dbg.nospace() << "QColor(AHSL " << c.alphaF() << ", " << c.hslHueF() << ", " << c.hslSaturationF() << ", " << c.lightnessF() << ')'; - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index f82b098012..61d57ca3f8 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -33,6 +33,7 @@ #include "qcosmeticstroker_p.h" #include "private/qpainterpath_p.h" +#include "private/qrgba64_p.h" #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -280,7 +281,7 @@ void QCosmeticStroker::setup() drawCaps = state->lastPen.capStyle() != Qt::FlatCap; if (strokeSelection & FastDraw) { - color = INTERPOLATE_PIXEL_256(state->penData.solid.color, opacity, 0, 0); + color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32(); QRasterBuffer *buffer = state->penData.rasterBuffer; pixels = (uint *)buffer->buffer(); ppl = buffer->bytesPerLine()>>2; @@ -602,8 +603,7 @@ void QCosmeticStroker::drawPath(const QVectorPath &path) if (!closed && drawCaps && points == end - 2) caps |= CapEnd; - QCosmeticStroker::Point last = this->lastPixel; - bool unclipped = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps); + bool moveNextStart = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps); /* fix for gaps in polylines with fastpen and aliased in a sequence of points with small distances: if current point p2 has been dropped @@ -613,14 +613,8 @@ void QCosmeticStroker::drawPath(const QVectorPath &path) still need to update p to avoid drawing the line after this one from a bad starting position. */ - if (fastPenAliased && unclipped) { - if (last.x != lastPixel.x || last.y != lastPixel.y - || points == begin + 2 || points == end - 2) { - p = p2; - } - } else { + if (!fastPenAliased || moveNextStart || points == begin + 2 || points == end - 2) p = p2; - } points += 2; caps = NoCaps; } @@ -727,8 +721,9 @@ template<DrawPixel drawPixel, class Dasher> static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps) { if (stroker->clipLine(rx1, ry1, rx2, ry2)) - return false; + return true; + bool didDraw = false; const int half = stroker->legacyRounding ? 31 : 0; int x1 = toF26Dot6(rx1) + half; int y1 = toF26Dot6(ry1) + half; @@ -814,6 +809,7 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, dasher.adjust(); x += xinc; } while (++y < ys); + didDraw = true; } } else { // horizontal @@ -889,10 +885,11 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, dasher.adjust(); y += yinc; } while (++x < xs); + didDraw = true; } } stroker->lastPixel = last; - return true; + return didDraw; } @@ -900,7 +897,7 @@ template<DrawPixel drawPixel, class Dasher> static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps) { if (stroker->clipLine(rx1, ry1, rx2, ry2)) - return false; + return true; int x1 = toF26Dot6(rx1); int y1 = toF26Dot6(ry1); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 538389f15f..b6f06135cd 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -51,6 +51,7 @@ #include <private/qdrawhelper_mips_dsp_p.h> #endif #include <private/qguiapplication_p.h> +#include <private/qrgba64_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE @@ -758,6 +759,35 @@ static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, in return const_cast<uint *>(layout->convertToARGB32PM(buffer, ptr, length, layout, 0)); } +static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + 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; +} + +template<QtPixelOrder PixelOrder> +static QRgba64 *QT_FASTCALL destFetch64RGB30(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] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]); + return buffer; +} static DestFetchProc destFetchProc[QImage::NImageFormats] = { @@ -788,6 +818,35 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = destFetch, // Format_Grayscale8 }; +static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destFetch64, // Format_Mono, + destFetch64, // Format_MonoLSB + 0, // Format_Indexed8 + destFetch64, // Format_RGB32 + destFetch64ARGB32, // Format_ARGB32, + destFetch64, // Format_ARGB32_Premultiplied + destFetch64, // Format_RGB16 + destFetch64, // Format_ARGB8565_Premultiplied + destFetch64, // Format_RGB666 + destFetch64, // Format_ARGB6666_Premultiplied + destFetch64, // Format_RGB555 + destFetch64, // Format_ARGB8555_Premultiplied + 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 + destFetch64, // Format_Alpha8 + destFetch64, // Format_Grayscale8 +}; + /* Returns the color in the mono destination color table that is the "nearest" to /color/. @@ -904,6 +963,51 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con } } +static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length) +{ + for (int i = 0; i < length; ++i) { + dest[i] = src[i].toArgb32(); + } +} + +static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint buf[buffer_size]; + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + StorePixelsFunc store = qStorePixels[layout->bpp]; + uchar *dest = rasterBuffer->scanLine(y); + while (length) { + int l = qMin(length, buffer_size); + const uint *ptr = 0; + convertFromRgb64(buf, buffer, l); + if (!layout->premultiplied && !layout->alphaWidth) + ptr = layout->convertFromRGB32(buf, buf, l, layout, 0); + else + ptr = layout->convertFromARGB32PM(buf, buf, l, layout, 0); + store(dest, ptr, x, l); + length -= l; + buffer += l; + x += l; + } +} + +static void QT_FASTCALL destStore64ARGB32(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] = 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; + for (int i = 0; i < length; ++i) { + dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]); + } +} + static DestStoreProc destStoreProc[QImage::NImageFormats] = { 0, // Format_Invalid @@ -933,6 +1037,35 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = destStore, // Format_Grayscale8 }; +static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destStore64, // Format_Mono, + destStore64, // Format_MonoLSB + 0, // Format_Indexed8 + destStore64, // Format_RGB32 + destStore64ARGB32, // Format_ARGB32, + destStore64, // Format_ARGB32_Premultiplied + destStore64, // Format_RGB16 + destStore64, // Format_ARGB8565_Premultiplied + destStore64, // Format_RGB666 + destStore64, // Format_ARGB6666_Premultiplied + destStore64, // Format_RGB555 + destStore64, // Format_ARGB8555_Premultiplied + destStore64, // Format_RGB888 + destStore64, // Format_RGB444 + destStore64, // Format_ARGB4444_Premultiplied + destStore64, // Format_RGBX8888 + destStore64, // Format_RGBA8888 + destStore64, // Format_RGBA8888_Premultiplied + destStore64RGB30<PixelOrderBGR>, // Format_BGR30 + destStore64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied + destStore64RGB30<PixelOrderRGB>, // Format_RGB30 + destStore64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied + destStore64, // Format_Alpha8 + destStore64, // Format_Grayscale8 +}; + /* Source fetches @@ -1539,40 +1672,29 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); const __m128i v_256 = _mm_set1_epi16(256); const __m128i v_disty = _mm_set1_epi16(disty); - __m128i v_fdx = _mm_set1_epi32(fdx*4); - - ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1); - - union Vect_buffer { __m128i vect; quint32 i[4]; }; - Vect_buffer v_fx; - - for (int i = 0; i < 4; i++) { - v_fx.i[i] = fx; - 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); while (b < boundedEnd) { - - Vect_buffer tl, tr, bl, br; - - for (int i = 0; i < 4; i++) { - int x1 = v_fx.i[i] >> 16; - const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1; - const uint *addr_tr = addr_tl + 1; - tl.i[i] = *addr_tl; - tr.i[i] = *addr_tr; - bl.i[i] = *(addr_tl+secondLine); - br.i[i] = *(addr_tr+secondLine); - } - __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12); + __m128i offset = _mm_srli_epi32(v_fx, 16); + const int offset0 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset1 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset2 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset3 = _mm_cvtsi128_si32(offset); + const __m128i tl = _mm_setr_epi32(s1[offset0], s1[offset1], s1[offset2], s1[offset3]); + const __m128i tr = _mm_setr_epi32(s1[offset0 + 1], s1[offset1 + 1], s1[offset2 + 1], s1[offset3 + 1]); + const __m128i bl = _mm_setr_epi32(s2[offset0], s2[offset1], s2[offset2], s2[offset3]); + const __m128i br = _mm_setr_epi32(s2[offset0 + 1], s2[offset1 + 1], s2[offset2 + 1], s2[offset3 + 1]); + + __m128i v_distx = _mm_srli_epi16(v_fx, 12); v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); - interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b); - b+=4; - v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx); + interpolate_4_pixels_16_sse2(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b); + b += 4; + v_fx = _mm_add_epi32(v_fx, v_fdx); } - fx = v_fx.i[0]; + fx = _mm_cvtsi128_si32(v_fx); #elif defined(__ARM_NEON__) BILINEAR_DOWNSCALE_BOUNDS_PROLOG @@ -1687,9 +1809,9 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c uint tr = s1[x2]; \ uint bl = s2[x1]; \ uint br = s2[x2]; \ - int distx = (fx & 0x0000ffff) >> 12; \ - int disty = (fy & 0x0000ffff) >> 12; \ - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \ + int distx = (fx & 0x0000ffff) >> 8; \ + int disty = (fy & 0x0000ffff) >> 8; \ + *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); \ fx += fdx; \ fy += fdy; \ ++b; \ @@ -1702,62 +1824,54 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); const __m128i v_256 = _mm_set1_epi16(256); - __m128i v_fdx = _mm_set1_epi32(fdx*4); - __m128i v_fdy = _mm_set1_epi32(fdy*4); + 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 uchar *textureData = data->texture.imageData; const int bytesPerLine = data->texture.bytesPerLine; - - union Vect_buffer { __m128i vect; qint32 i[4]; }; - Vect_buffer v_fx, v_fy; - - for (int i = 0; i < 4; i++) { - v_fx.i[i] = fx; - v_fy.i[i] = fy; - fx += fdx; - fy += fdy; - } + const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0)); while (b < boundedEnd) { - if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2) + if (fdx > 0 && (short)_mm_extract_epi16(v_fx, 7) >= image_x2) break; - if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1) + if (fdx < 0 && (short)_mm_extract_epi16(v_fx, 7) < image_x1) break; - if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2) + if (fdy > 0 && (short)_mm_extract_epi16(v_fy, 7) >= image_y2) break; - if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1) + if (fdy < 0 && (short)_mm_extract_epi16(v_fy, 7) < image_y1) break; - Vect_buffer tl, tr, bl, br; - Vect_buffer v_fx_shifted, v_fy_shifted; - v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16); - v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16); - - for (int i = 0; i < 4; i++) { - const int x1 = v_fx_shifted.i[i]; - const int y1 = v_fy_shifted.i[i]; - const uchar *sl = textureData + bytesPerLine * y1; - const uint *s1 = (const uint *)sl; - const uint *s2 = (const uint *)(sl + bytesPerLine); - tl.i[i] = s1[x1]; - tr.i[i] = s1[x1+1]; - bl.i[i] = s2[x1]; - br.i[i] = s2[x1+1]; - } - __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12); - __m128i v_disty = _mm_srli_epi16(v_fy.vect, 12); + const __m128i vy = _mm_packs_epi32(_mm_srli_epi32(v_fy, 16), _mm_setzero_si128()); + // 4x16bit * 4x16bit -> 4x32bit + __m128i offset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epi16(vy, vbpl)); + offset = _mm_add_epi32(offset, _mm_srli_epi32(v_fx, 16)); + const int offset0 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset1 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset2 = _mm_cvtsi128_si32(offset); offset = _mm_srli_si128(offset, 4); + const int offset3 = _mm_cvtsi128_si32(offset); + const uint *topData = (const uint *)(textureData); + const __m128i tl = _mm_setr_epi32(topData[offset0], topData[offset1], topData[offset2], topData[offset3]); + const __m128i tr = _mm_setr_epi32(topData[offset0 + 1], topData[offset1 + 1], topData[offset2 + 1], topData[offset3 + 1]); + const uint *bottomData = (const uint *)(textureData + bytesPerLine); + const __m128i bl = _mm_setr_epi32(bottomData[offset0], bottomData[offset1], bottomData[offset2], bottomData[offset3]); + const __m128i br = _mm_setr_epi32(bottomData[offset0 + 1], bottomData[offset1 + 1], bottomData[offset2 + 1], bottomData[offset3 + 1]); + + __m128i v_distx = _mm_srli_epi16(v_fx, 12); + __m128i v_disty = _mm_srli_epi16(v_fy, 12); v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0)); v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0)); - interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b); - b+=4; - v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx); - v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy); + interpolate_4_pixels_16_sse2(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b); + b += 4; + v_fx = _mm_add_epi32(v_fx, v_fdx); + v_fy = _mm_add_epi32(v_fy, v_fdy); } - fx = v_fx.i[0]; - fy = v_fy.i[0]; + fx = _mm_cvtsi128_si32(v_fx); + fy = _mm_cvtsi128_si32(v_fy); #endif } @@ -1778,10 +1892,16 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c uint bl = s2[x1]; uint br = s2[x2]; +#if defined(__SSE2__) + // The SSE2 optimized interpolate_4_pixels is faster than interpolate_4_pixels_16. + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); +#else int distx = (fx & 0x0000ffff) >> 12; int disty = (fy & 0x0000ffff) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); +#endif fx += fdx; fy += fdy; @@ -2334,6 +2454,12 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos) +{ + int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -2418,6 +2544,75 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope return b; } +static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + const QRgba64 *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); + } + } + + const QRgba64 *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); + } 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_pixel64_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_pixel64(&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_pixel64(&data->gradient, t); + rx += data->m11; + ry += data->m12; + rw += data->m13; + if (!rw) { + rw += data->m13; + } + ++buffer; + } + } + + return b; +} + static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data) { v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; @@ -2573,11 +2768,35 @@ void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_ 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 @@ -2597,6 +2816,19 @@ void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint } } +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) { @@ -2611,14 +2843,34 @@ void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL } } +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 @@ -2640,6 +2892,19 @@ void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint 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) @@ -2661,6 +2926,24 @@ void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_ } } +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 @@ -2678,6 +2961,16 @@ void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint co } } +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) @@ -2697,6 +2990,22 @@ void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uin } } +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 @@ -4237,7 +4546,21 @@ static CompositionFunctionSolid functionForModeSolid_C[] = { rasterop_solid_NotDestination }; +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, @@ -4280,7 +4603,21 @@ static CompositionFunction functionForMode_C[] = { 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 +}; + static const CompositionFunction *functionForMode = functionForMode_C; +static const CompositionFunction64 *functionForMode64 = functionForMode64_C; static TextureBlendType getBlendType(const QSpanData *data) { @@ -4310,24 +4647,28 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in switch(data->type) { case QSpanData::Solid: - solidSource = (qAlpha(data->solid.color) == 255); + solidSource = data->solid.color.isOpaque(); break; case QSpanData::LinearGradient: solidSource = !data->gradient.alphaColor; getLinearGradientValues(&op.linear, data); - op.src_fetch = qt_fetch_linear_gradient; + op.srcFetch = qt_fetch_linear_gradient; + op.srcFetch64 = qt_fetch_linear_gradient_rgb64; break; case QSpanData::RadialGradient: solidSource = !data->gradient.alphaColor; getRadialGradientValues(&op.radial, data); - op.src_fetch = qt_fetch_radial_gradient; + op.srcFetch = qt_fetch_radial_gradient; + op.srcFetch64 = 0; //qt_fetch_radial_gradient_rgb64; break; case QSpanData::ConicalGradient: solidSource = !data->gradient.alphaColor; - op.src_fetch = qt_fetch_conical_gradient; + op.srcFetch = qt_fetch_conical_gradient; + op.srcFetch64 = 0; //qt_fetch_conical_gradient_rgb64; break; case QSpanData::Texture: - op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format]; + op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format]; + op.srcFetch64 = 0; // sourceFetch64[getBlendType(data)][data->texture.format]; solidSource = !data->texture.hasAlpha; default: break; @@ -4337,12 +4678,13 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in if (op.mode == QPainter::CompositionMode_SourceOver && solidSource) op.mode = QPainter::CompositionMode_Source; - op.dest_fetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch64 = destFetchProc64[data->rasterBuffer->format]; if (op.mode == QPainter::CompositionMode_Source) { switch (data->rasterBuffer->format) { case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: - // don't clear dest_fetch as it sets up the pointer correctly to save one copy + // don't clear destFetch as it sets up the pointer correctly to save one copy break; default: { if (data->type == QSpanData::Texture && data->texture.const_alpha != 256) @@ -4356,16 +4698,21 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in } ++spans; } - if (!alphaSpans) - op.dest_fetch = 0; + if (!alphaSpans) { + op.destFetch = 0; + op.destFetch64 = 0; + } } } } - op.dest_store = destStoreProc[data->rasterBuffer->format]; + op.destStore = destStoreProc[data->rasterBuffer->format]; + op.destStore64 = destStoreProc64[data->rasterBuffer->format]; op.funcSolid = functionForModeSolid[op.mode]; + op.funcSolid64 = functionForModeSolid64[op.mode]; op.func = functionForMode[op.mode]; + op.func64 = functionForMode64[op.mode]; return op; } @@ -4382,16 +4729,17 @@ void blend_color_generic(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); uint buffer[buffer_size]; Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); while (count--) { int x = spans->x; int length = spans->len; while (length) { int l = qMin(buffer_size, length); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; - op.funcSolid(dest, l, data->solid.color, spans->coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.funcSolid(dest, l, color, spans->coverage); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); length -= l; x += l; } @@ -4404,15 +4752,16 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); if (op.mode == QPainter::CompositionMode_Source) { // inline for performance while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { - QT_MEMFILL_UINT(target, spans->len, data->solid.color); + QT_MEMFILL_UINT(target, spans->len, color); } else { - uint c = BYTE_MUL(data->solid.color, spans->coverage); + uint c = BYTE_MUL(color, spans->coverage); int ialpha = 255 - spans->coverage; for (int i = 0; i < spans->len; ++i) target[i] = c + BYTE_MUL(target[i], ialpha); @@ -4424,7 +4773,35 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; - op.funcSolid(target, spans->len, data->solid.color, spans->coverage); + op.funcSolid(target, spans->len, color, spans->coverage); + ++spans; + } +} + +void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + if (!op.funcSolid64) { + qDebug() << Q_FUNC_INFO << "unsupported 64bit blend attempted"; + return blend_color_generic(count, spans, userData); + } + + QRgba64 buffer[buffer_size]; + const QRgba64 color = data->solid.color; + + while (count--) { + int x = spans->x; + 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; + op.funcSolid64(dest, l, color, spans->coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); + length -= l; + x += l; + } ++spans; } } @@ -4439,13 +4816,12 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) from qt_gradient_quint16 with minimal overhead. */ QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode == QPainter::CompositionMode_SourceOver && - qAlpha(data->solid.color) == 255) + if (mode == QPainter::CompositionMode_SourceOver && data->solid.color.isOpaque()) mode = QPainter::CompositionMode_Source; if (mode == QPainter::CompositionMode_Source) { // inline for performance - ushort c = qConvertRgb32To16(data->solid.color); + ushort c = data->solid.color.toRgb16(); while (count--) { ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { @@ -4466,7 +4842,7 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) if (mode == QPainter::CompositionMode_SourceOver) { while (count--) { - uint color = BYTE_MUL(data->solid.color, spans->coverage); + uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage); int ialpha = qAlpha(~color); ushort c = qConvertRgb32To16(color); ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; @@ -4530,7 +4906,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle int process_length = l; int process_x = x; - const uint *src = handler.fetch(process_x, y, process_length); + const typename T::BlendType *src = handler.fetch(process_x, y, process_length); int offset = 0; while (l > 0) { if (x == spans->x) // new span? @@ -4555,8 +4931,10 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle } } +template<typename T> struct QBlendBase { + typedef T BlendType; QBlendBase(QSpanData *d, Operator o) : data(d) , op(o) @@ -4567,24 +4945,24 @@ struct QBlendBase QSpanData *data; Operator op; - uint *dest; + BlendType *dest; - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; + BlendType buffer[buffer_size]; + BlendType src_buffer[buffer_size]; }; -class BlendSrcGeneric : public QBlendBase +class BlendSrcGeneric : public QBlendBase<uint> { public: BlendSrcGeneric(QSpanData *d, Operator o) - : QBlendBase(d, o) + : QBlendBase<uint>(d, o) { } const uint *fetch(int x, int y, int len) { - dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer; - return op.src_fetch(src_buffer, &op, data, y, x, len); + dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, y, len) : buffer; + return op.srcFetch(src_buffer, &op, data, y, x, len); } void process(int, int, int len, int coverage, const uint *src, int offset) @@ -4594,8 +4972,38 @@ public: void store(int x, int y, int len) { - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, y, dest, len); + if (op.destStore) + op.destStore(data->rasterBuffer, x, y, dest, len); + } +}; + +class BlendSrcGenericRGB64 : public QBlendBase<QRgba64> +{ +public: + BlendSrcGenericRGB64(QSpanData *d, Operator o) + : QBlendBase<QRgba64>(d, o) + { + } + + bool isSupported() const + { + return op.srcFetch64 && op.func64; + } + + const QRgba64 *fetch(int x, int y, int len) + { + dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len); + return op.srcFetch64(src_buffer, &op, data, y, x, len); + } + + void process(int, int, int len, int coverage, const QRgba64 *src, int offset) + { + op.func64(dest + offset, src + offset, len, coverage); + } + + void store(int x, int y, int len) + { + op.destStore64(data->rasterBuffer, x, y, dest, len); } }; @@ -4606,6 +5014,20 @@ static void blend_src_generic(int count, const QSpan *spans, void *userData) handleSpans(count, spans, data, blend); } +static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + BlendSrcGenericRGB64 blend64(data, op); + if (blend64.isSupported()) + handleSpans(count, spans, data, blend64); + else { + qDebug("blend_src_generic_rgb64: unsupported 64-bit blend attempted"); + BlendSrcGeneric blend32(data, op); + handleSpans(count, spans, data, blend32); + } +} + static void blend_untransformed_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -4636,11 +5058,60 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(buffer_size, length); - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + } + } + } + ++spans; + } +} + +static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.srcFetch64 || !op.func64) { + qWarning() << Q_FUNC_INFO << "Unsupported blend"; + return blend_untransformed_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx); + int yoff = -qRound(-data->dy); + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = xoff + x; + int sy = yoff + spans->y; + if (sy >= 0 && sy < image_height && sx < image_width) { + if (sx < 0) { + x -= sx; + length += sx; + sx = 0; + } + if (sx + length > image_width) + length = image_width - sx; + if (length > 0) { + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + 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; + op.func64(dest, src, l, coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -4829,11 +5300,63 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData) int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + if (sx >= image_width) + sx = 0; + } + ++spans; + } +} + +static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.srcFetch64 || !op.func64) { + qDebug("unsupported rgb64 blend"); + return blend_tiled_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx) % image_width; + int yoff = -qRound(-data->dy) % image_height; + + if (xoff < 0) + xoff += image_width; + if (yoff < 0) + yoff += image_height; + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = (xoff + spans->x) % image_width; + int sy = (spans->y + yoff) % image_height; + if (sx < 0) + sx += image_width; + if (sy < 0) + sy += image_height; + + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + while (length) { + int l = qMin(image_width - sx, length); + 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; + op.func64(dest, src, l, coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -5714,10 +6237,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_untransformed_generic, blend_untransformed_generic, blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, blend_untransformed_generic, blend_untransformed_generic, }, @@ -5742,10 +6265,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_tiled_generic, blend_tiled_generic, blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, blend_tiled_generic, blend_tiled_generic, }, @@ -5770,10 +6293,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5797,12 +6320,12 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic }, // Bilinear { @@ -5825,10 +6348,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5853,10 +6376,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, // RGBX8888 blend_src_generic, // RGBA8888 blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic, // BGR30 - blend_src_generic, // A2BGR30_Premultiplied - blend_src_generic, // RGB30 - blend_src_generic, // A2RGB30_Premultiplied + blend_src_generic_rgb64, // BGR30 + blend_src_generic_rgb64, // A2BGR30_Premultiplied + blend_src_generic_rgb64, // RGB30 + blend_src_generic_rgb64, // A2RGB30_Premultiplied blend_src_generic, // Alpha8 blend_src_generic, // Grayscale8 } @@ -6012,13 +6535,11 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); - uint oldColor = data->solid.color; + QRgba64 oldColor = data->solid.color; while (count--) { int y = spans->y; - quint32 color = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); - - data->solid.color = color; + data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off)); blend_color_rgb16(1, spans, userData); ++spans; } @@ -6030,39 +6551,39 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) } inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color, + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color), + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint16>(rasterBuffer, x, y, qConvertRgb32To16(color), + qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color.toRgb16(), map, mapWidth, mapHeight, mapStride); } static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = color.toRgb16(); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); @@ -6160,7 +6681,7 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in } #endif -static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, +static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, int mapWidth, int mapHeight, int mapStride, @@ -6256,28 +6777,38 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, } } + +static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, const QRgba64 &color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) +{ + qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip); +} + #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *clip) { - qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); + qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip); } #endif static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *src, int mapWidth, int mapHeight, int srcStride, const QClipData *clip) { - const quint32 c = color; + const quint32 c = color.toArgb32(); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - int sa = qAlpha(color); + int sr = qRed(c); + int sg = qGreen(c); + int sb = qBlue(c); + int sa = qAlpha(c); const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables(); if (!tables) @@ -6344,58 +6875,67 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, static void qt_rectfill_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - color, x, y, width, height, rasterBuffer->bytesPerLine()); + color.toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()), - qConvertRgb32To16(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.toRgb16(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.unpremultiplied().toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(color), x, y, width, height, rasterBuffer->bytesPerLine()); + ARGB2RGBA(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) +{ + qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), + ARGB2RGBA(color.unpremultiplied().toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); +} + +template<QtPixelOrder PixelOrder> +static void qt_rectfill_rgb30(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine()); + qConvertRgb64ToRgb30<PixelOrder>(color), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_alpha(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qAlpha(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.alpha() >> 8, x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_gray(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qGray(color), x, y, width, height, rasterBuffer->bytesPerLine()); + qGray(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } // Map table for destination image format. Contains function pointers @@ -6548,39 +7088,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = }, // Format_BGR30 { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_RGB30 { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_Alpha8 { @@ -6649,6 +7189,11 @@ inline void qt_memfill_template(quint16 *dest, quint16 value, int count) } #endif +void qt_memfill64(quint64 *dest, quint64 color, int count) +{ + qt_memfill_template<quint64>(dest, color, count); +} + #if !defined(__SSE2__) void qt_memfill16(quint16 *dest, quint16 color, int count) { diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 7e12e62151..36e2488a94 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -466,7 +466,7 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, } void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *) @@ -475,8 +475,9 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); uchar *mask = const_cast<uchar *>(bitmap); + const uint c = color.toArgb32(); - pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride); + pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, c, 0, mask, mapStride); } extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha); diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index bd030a8bf3..37e060f147 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -82,7 +82,7 @@ void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, int const_alpha); void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 480ba4c97b..501f1ce033 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -50,6 +50,7 @@ #include "QtGui/qcolor.h" #include "QtGui/qpainter.h" #include "QtGui/qimage.h" +#include "QtGui/qrgba64.h" #ifndef QT_FT_BEGIN_HEADER #define QT_FT_BEGIN_HEADER #define QT_FT_END_HEADER @@ -99,25 +100,25 @@ class QRasterPaintEngineState; typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride); typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *rgbmask, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color); + const QRgba64 &color); typedef void (*SrcOverBlendFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, @@ -158,11 +159,14 @@ extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; void qBlendTexture(int count, const QSpan *spans, void *userData); +extern void qt_memfill64(quint64 *dest, quint64 value, int count); extern void qt_memfill32(quint32 *dest, quint32 value, int count); extern void qt_memfill16(quint16 *dest, quint16 value, int count); typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha); struct LinearGradientValues { @@ -185,17 +189,27 @@ struct RadialGradientValues struct Operator; typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); +typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); +typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length); typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); +typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); struct Operator { QPainter::CompositionMode mode; - DestFetchProc dest_fetch; - DestStoreProc dest_store; - SourceFetchProc src_fetch; + DestFetchProc destFetch; + DestStoreProc destStore; + SourceFetchProc srcFetch; CompositionFunctionSolid funcSolid; CompositionFunction func; + + DestFetchProc64 destFetch64; + DestStoreProc64 destStore64; + SourceFetchProc64 srcFetch64; + CompositionFunctionSolid64 funcSolid64; + CompositionFunction64 func64; + union { LinearGradientValues linear; RadialGradientValues radial; @@ -208,7 +222,7 @@ class QRasterPaintEngine; struct QSolidData { - uint color; + QRgba64 color; }; struct QLinearGradientData @@ -259,7 +273,7 @@ struct QGradientData #define GRADIENT_STOPTABLE_SIZE 1024 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10 - uint* colorTable; //[GRADIENT_STOPTABLE_SIZE]; + QRgba64* colorTable; //[GRADIENT_STOPTABLE_SIZE]; uint alphaColor : 1; }; @@ -367,6 +381,12 @@ static inline uint qt_gradient_clamp(const QGradientData *data, int ipos) static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) { int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static inline const QRgba64& qt_gradient_pixel64(const QGradientData *data, qreal pos) +{ + int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -526,7 +546,7 @@ public: delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \ for (int i = 0; i < 4; ++i) \ - *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \ + *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]].toArgb32(); \ } #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \ @@ -644,7 +664,8 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { return t; } -static Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } static Q_ALWAYS_INLINE uint BYTE_MUL_RGB30(uint x, uint a) { uint xa = x >> 30; @@ -687,6 +708,11 @@ inline quint24::operator uint() const template <class T> Q_STATIC_TEMPLATE_FUNCTION void qt_memfill(T *dest, T value, int count); +template<> inline void qt_memfill(quint64 *dest, quint64 color, int count) +{ + qt_memfill64(dest, color, count); +} + template<> inline void qt_memfill(quint32 *dest, quint32 color, int count) { qt_memfill32(dest, color, count); @@ -871,6 +897,64 @@ inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c) | ((c >> 2) & 0x000000ff); } +template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb); + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 blue = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 red = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 red = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 blue = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64); + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (b << 20) | (g << 10) | r; +} + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (r << 20) | (g << 10) | b; +} + inline uint qRgbSwapRgb30(uint c) { const uint ag = c & 0xc00ffc00; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 84eb3b7909..b8957fe2fb 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -417,7 +417,7 @@ void qt_memfill16(quint16 *dest, quint16 value, int count) dest[count - 1] = value; } -void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, +void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) { @@ -468,18 +468,25 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, } } +void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, + const QRgba64 &color, + const uchar *src, int width, int height, int stride) +{ + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, color.toArgb32(), src, width, height, stride); +} + void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - qt_bitmapblit32_sse2(rasterBuffer, x, y, ARGB2RGBA(color), src, width, height, stride); + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), src, width, height, stride); } void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = qConvertRgb32To16(color.toArgb32()); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 4d203c4f9d..50ee83aa2c 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -53,13 +53,13 @@ QT_BEGIN_NAMESPACE void qt_memfill32(quint32 *dest, quint32 value, int count); void qt_memfill16(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 679b5000cb..acedc6a7ba 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -1130,6 +1130,7 @@ QDataStream &operator>>(QDataStream &s, QMatrix &m) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QMatrix &m) { + QDebugStateSaver saver(dbg); dbg.nospace() << "QMatrix(" << "11=" << m.m11() << " 12=" << m.m12() @@ -1138,7 +1139,7 @@ QDebug operator<<(QDebug dbg, const QMatrix &m) << " dx=" << m.dx() << " dy=" << m.dy() << ')'; - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp index c1b23960ad..f443bbd5ac 100644 --- a/src/gui/painting/qpagelayout.cpp +++ b/src/gui/painting/qpagelayout.cpp @@ -942,6 +942,7 @@ QRect QPageLayout::paintRectPixels(int resolution) const #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QPageLayout &layout) { + QDebugStateSaver saver(dbg); if (layout.isValid()) { QString output = QStringLiteral("QPageLayout(%1, %2, l:%3 r:%4 t:%5 b:%6 %7)"); QString units; @@ -976,7 +977,7 @@ QDebug operator<<(QDebug dbg, const QPageLayout &layout) } else { dbg.nospace() << "QPageLayout()"; } - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp index fe445c0aec..c0aae603b7 100644 --- a/src/gui/painting/qpagesize.cpp +++ b/src/gui/painting/qpagesize.cpp @@ -1854,6 +1854,7 @@ QSize QPageSize::sizePixels(PageSizeId pageSizeId, int resolution) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QPageSize &pageSize) { + QDebugStateSaver saver(dbg); if (pageSize.isValid()) { QString output = QStringLiteral("QPageSize(\"%1\", \"%2\", %3x%4pt, %5)"); output = output.arg(pageSize.name()) @@ -1865,7 +1866,7 @@ QDebug operator<<(QDebug dbg, const QPageSize &pageSize) } else { dbg.nospace() << "QPageSize()"; } - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 18522cb6d0..3be6e0f1f4 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -57,6 +57,7 @@ #include <private/qstatictext_p.h> #include <private/qcosmeticstroker_p.h> #include "qmemrotate_p.h" +#include "qrgba64_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -830,7 +831,7 @@ void QRasterPaintEngine::updateRasterState() && s->intOpacity == 256 && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(s->penData.solid.color) == 255)); + && s->penData.solid.color.isOpaque())); } s->dirty = 0; @@ -1412,10 +1413,9 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, if (data->fillRect && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(data->solid.color) == 255))) + && data->solid.color.isOpaque()))) { - data->fillRect(data->rasterBuffer, x1, y1, width, height, - data->solid.color); + data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color); return; } } @@ -1773,8 +1773,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity)); + + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) { return; } @@ -2219,19 +2220,15 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe case QImage::Format_A2BGR30_Premultiplied: case QImage::Format_A2RGB30_Premultiplied: // Combine premultiplied color with the opacity set on the painter. - d->solid_color_filler.solid.color = - ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) - | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + d->solid_color_filler.solid.color = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity); break; default: - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity)); break; } - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 - && s->composition_mode == QPainter::CompositionMode_SourceOver) { + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) return; - } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); @@ -4137,7 +4134,7 @@ class QGradientCache { inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : stops(s), opacity(op), interpolationMode(mode) {} - uint buffer[GRADIENT_STOPTABLE_SIZE]; + QRgba64 buffer[GRADIENT_STOPTABLE_SIZE]; QGradientStops stops; int opacity; QGradient::InterpolationMode interpolationMode; @@ -4146,12 +4143,12 @@ class QGradientCache typedef QMultiHash<quint64, CacheInfo> QGradientColorTableHash; public: - inline const uint *getBuffer(const QGradient &gradient, int opacity) { + inline const QRgba64 *getBuffer(const QGradient &gradient, int opacity) { quint64 hash_val = 0; QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); + hash_val += stops[i].second.rgba64(); QMutexLocker lock(&mutex); QGradientColorTableHash::const_iterator it = cache.constFind(hash_val); @@ -4174,9 +4171,9 @@ public: protected: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& g, - uint *colorTable, + QRgba64 *colorTable, int size, int opacity) const; - uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { + QRgba64 *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK cache.erase(cache.begin() + (qrand() % maxCacheSize())); @@ -4190,7 +4187,7 @@ protected: QMutex mutex; }; -void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const +void QGradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, int opacity) const { QGradientStops stops = gradient.stops(); int stopCount = stops.count(); @@ -4199,14 +4196,16 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); if (stopCount == 2) { - uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); - uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity); + QRgba64 first_color = combineAlpha256(stops[0].second.rgba64(), opacity); + QRgba64 second_color = combineAlpha256(stops[1].second.rgba64(), opacity); qreal first_stop = stops[0].first; qreal second_stop = stops[1].first; if (second_stop < first_stop) { - qSwap(first_color, second_color); + quint64 tmp = first_color; + first_color = second_color; + second_color = tmp; qSwap(first_stop, second_stop); } @@ -4218,15 +4217,15 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1)); - uint red_first = qRed(first_color) << 16; - uint green_first = qGreen(first_color) << 16; - uint blue_first = qBlue(first_color) << 16; - uint alpha_first = qAlpha(first_color) << 16; + uint red_first = uint(first_color.red()) << 16; + uint green_first = uint(first_color.green()) << 16; + uint blue_first = uint(first_color.blue()) << 16; + uint alpha_first = uint(first_color.alpha()) << 16; - uint red_second = qRed(second_color) << 16; - uint green_second = qGreen(second_color) << 16; - uint blue_second = qBlue(second_color) << 16; - uint alpha_second = qAlpha(second_color) << 16; + uint red_second = uint(second_color.red()) << 16; + uint green_second = uint(second_color.green()) << 16; + uint blue_second = uint(second_color.blue()) << 16; + uint alpha_second = uint(second_color.alpha()) << 16; int i = 0; for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) { @@ -4239,10 +4238,10 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (i < second_index) { qreal reciprocal = qreal(1) / (second_index - first_index); - int red_delta = qRound(int(red_second - red_first) * reciprocal); - int green_delta = qRound(int(green_second - green_first) * reciprocal); - int blue_delta = qRound(int(blue_second - blue_first) * reciprocal); - int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal); + int red_delta = qRound((qreal(red_second) - red_first) * reciprocal); + int green_delta = qRound((qreal(green_second) - green_first) * reciprocal); + int blue_delta = qRound((qreal(blue_second) - blue_first) * reciprocal); + int alpha_delta = qRound((qreal(alpha_second) - alpha_first) * reciprocal); // rounding red_first += 1 << 15; @@ -4256,8 +4255,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint blue_first += blue_delta; alpha_first += alpha_delta; - const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000) - | ((green_first >> 8) & 0xff00) | (blue_first >> 16); + const QRgba64 color = qRgba64(red_first >> 16, green_first >> 16, blue_first >> 16, alpha_first >> 16); if (colorInterpolation) colorTable[i] = color; @@ -4276,7 +4274,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint return; } - uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); + QRgba64 current_color = combineAlpha256(stops[0].second.rgba64(), opacity); if (stopCount == 1) { current_color = qPremultiply(current_color); for (int i = 0; i < size; ++i) @@ -4289,7 +4287,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint qreal end_pos = stops[stopCount-1].first; int pos = 0; // The position in the color table. - uint next_color; + QRgba64 next_color; qreal incr = 1 / qreal(size); // the double increment. qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) @@ -4313,8 +4311,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint ++current_stop; if (current_stop != 0) - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { current_color = qPremultiply(current_color); @@ -4333,9 +4331,9 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); else - colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); ++pos; dpos += incr; @@ -4354,8 +4352,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (skip == 1) current_color = next_color; else - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { if (skip != 1) @@ -4372,7 +4370,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } // After last point - current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); + current_color = qPremultiply(combineAlpha256(stops[stopCount - 1].second.rgba64(), opacity)); while (pos < size - 1) { colorTable[pos] = current_color; ++pos; @@ -4405,12 +4403,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode case Qt::SolidPattern: { type = Solid; QColor c = qbrush_color(brush); - QRgb rgba = c.rgba(); - solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha)); - if ((solid.color & 0xff000000) == 0 - && compositionMode == QPainter::CompositionMode_SourceOver) { + solid.color = qPremultiply(combineAlpha256(c.rgba64(), alpha)); + if (solid.color.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver) type = None; - } break; } @@ -4419,7 +4414,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = LinearGradient; const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QLinearGradientData &linearData = gradient.linear; @@ -4436,7 +4431,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = RadialGradient; const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QRadialGradientData &radialData = gradient.radial; @@ -4457,7 +4452,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = ConicalGradient; const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = QGradient::RepeatSpread; QConicalGradientData &conicalData = gradient.conical; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 69cbb42923..70862ea583 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7462,6 +7462,7 @@ start_lengthVariant: range.format.setFontUnderline(true); underlineFormats.append(range); } +#ifdef Q_OS_MAC } else if (hidemnmemonic && *cin == QLatin1Char('(') && l >= 4 && cin[1] == QLatin1Char('&') && cin[2] != QLatin1Char('&') && cin[3] == QLatin1Char(')')) { @@ -7473,6 +7474,7 @@ start_lengthVariant: length -= n + 4; l -= 4; continue; +#endif //Q_OS_MAC } *cout = *cin; ++cout; diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 4796d2c0ad..6263d18b01 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -1026,12 +1026,13 @@ QDebug operator<<(QDebug dbg, const QPen &p) "CustomDashLine" }; + QDebugStateSaver saver(dbg); dbg.nospace() << "QPen(" << p.width() << ',' << p.brush() << ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle()) << ',' << int(p.joinStyle()) << ',' << p.dashPattern() << ',' << p.dashOffset() << ',' << p.miterLimit() << ')'; - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp index 511af49787..efcc8875a5 100644 --- a/src/gui/painting/qpolygon.cpp +++ b/src/gui/painting/qpolygon.cpp @@ -461,11 +461,12 @@ QRect QPolygon::boundingRect() const #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QPolygon &a) { + QDebugStateSaver saver(dbg); dbg.nospace() << "QPolygon("; for (int i = 0; i < a.count(); ++i) dbg.nospace() << a.at(i); dbg.nospace() << ')'; - return dbg.space(); + return dbg; } #endif @@ -802,11 +803,12 @@ QDataStream &operator>>(QDataStream &s, QPolygonF &a) #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QPolygonF &a) { + QDebugStateSaver saver(dbg); dbg.nospace() << "QPolygonF("; for (int i = 0; i < a.count(); ++i) dbg.nospace() << a.at(i); dbg.nospace() << ')'; - return dbg.space(); + return dbg; } #endif diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index 2ea09e6bd6..51ce4ab10d 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -88,6 +88,9 @@ public: return fromRgba(rgb >> 16, rgb >> 8, rgb, rgb >> 24); } + Q_DECL_CONSTEXPR bool isOpaque() const { return c.alpha == 0xffff; } + Q_DECL_CONSTEXPR bool isTransparent() const { return c.alpha == 0; } + Q_DECL_CONSTEXPR quint16 red() const { return c.red; } Q_DECL_CONSTEXPR quint16 green() const { return c.green; } Q_DECL_CONSTEXPR quint16 blue() const { return c.blue; } @@ -133,6 +136,12 @@ public: return rgba; } + QRgba64 operator=(quint64 _rgba) + { + rgba = _rgba; + return *this; + } + private: static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); } diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h new file mode 100644 index 0000000000..a1452af8d9 --- /dev/null +++ b/src/gui/painting/qrgba64_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QRGBA64_P_H +#define QRGBA64_P_H + +#include <QtGui/qrgba64.h> +#include <QtGui/private/qdrawhelper_p.h> + +QT_BEGIN_NAMESPACE + +inline QRgba64 combineAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64(rgba64.red(), rgba64.green(), rgba64.blue(), (rgba64.alpha() * alpha256) >> 8); +} + +inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8, + (rgba64.green() * alpha256) >> 8, + (rgba64.blue() * alpha256) >> 8, + (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) +{ + 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)); +} + +inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2)); +} + +inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2)); +} + +QT_END_NAMESPACE + +#endif // QRGBA64_P_H diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 881fae9afc..4c879cf05d 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -123,17 +123,6 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; - // This is a rather crude hack, but it works. - // The FreeType font engine is not capable of getting precise metrics for the alphamap - // without first rasterizing the glyph. If we force the glyph to be rasterized before - // we ask for the alphaMapBoundingBox(), the glyph will be loaded, rasterized and its - // proper metrics will be cached and used later. - if (fontEngine->hasInternalCaching()) { - QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, m_format); - if (locked && !locked->isNull()) - fontEngine->unlockAlphaMapForGlyph(); - } - glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, m_format); #ifdef CACHE_DEBUG diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 4c1aff92ae..31d7a2300b 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1091,6 +1091,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m) "TxProject" }; + QDebugStateSaver saver(dbg); dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ',' << " 11=" << m.m11() << " 12=" << m.m12() @@ -1103,7 +1104,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m) << " 33=" << m.m33() << ')'; - return dbg.space(); + return dbg; } #endif |