From 84a71a1b9e600dc641e7ace5a6b384c0e138753e Mon Sep 17 00:00:00 2001 From: Fabian Vogt Date: Wed, 25 Dec 2019 18:55:01 +0100 Subject: [PATCH 3/3] Revert "Handle transparent pen color in fast text path" This reverts commit d0d18b06458edd3b6b0712ea71c787404bbaa7e1. --- src/gui/painting/qdrawhelper.cpp | 187 +++++++++++------------ src/gui/painting/qdrawhelper_p.h | 2 - src/gui/painting/qpaintengine_raster.cpp | 4 +- src/gui/painting/qrgba64_p.h | 2 - 4 files changed, 94 insertions(+), 101 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 3d06a27d8e..edb363ac69 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5658,60 +5658,44 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL { if (coverage == 0) { // nothing - } else if (coverage == 255 || !colorProfile) { - blend_pixel(*dst, src, coverage); - } else if (*dst < 0xff000000) { - // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 - blend_pixel(*dst, src, coverage); - } else if (src >= 0xff000000) { - grayBlendPixel(dst, coverage, srcLinear, colorProfile); + } else if (coverage == 255) { + *dst = src; + } else if (!colorProfile) { + *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage); } else { - // First do naive blend with text-color - QRgb s = *dst; - blend_pixel(s, src); - // Then gamma-corrected blend with glyph shape - grayBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); + if (*dst >= 0xff000000) { + grayBlendPixel(dst, coverage, srcLinear, colorProfile); + } else { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage); + } } } #if QT_CONFIG(raster_64bit) - -static inline void grayBlendPixel(QRgba64 &dst, int coverage, QRgba64 srcLinear, const QColorTrcLut *colorProfile) -{ - // Do a gammacorrected gray alphablend... - QRgba64 dstColor = dst; - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->toLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); - } - - blend_pixel(dstColor, srcLinear, coverage); - - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->fromLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); - } - dst = dstColor; -} - static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) { if (coverage == 0) { // nothing } else if (coverage == 255) { - blend_pixel(dest[x], src); - } else if (src.isOpaque()) { - grayBlendPixel(dest[x], coverage, srcLinear, colorProfile); + dest[x] = src; } else { - // First do naive blend with text-color - QRgba64 s = dest[x]; - blend_pixel(s, src); - // Then gamma-corrected blend with glyph shape - grayBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); + QRgba64 dstColor = dest[x]; + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->toLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); + } + + dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - coverage); + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->fromLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); + } + dest[x] = dstColor; } } @@ -5730,8 +5714,12 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -5804,8 +5792,12 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } quint32 buffer[BufferSize]; const DestFetchProc destFetch = destFetchProc[rasterBuffer->format]; @@ -5880,7 +5872,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, int mapWidth, int mapHeight, int mapStride, const QClipData *clip, bool useGammaCorrection) { - if (useGammaCorrection || !color.isOpaque()) { + if (useGammaCorrection) { qt_alphamapblit_generic(rasterBuffer, x, y, color, map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection); return; } @@ -5939,8 +5931,12 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } if (!clip) { quint32 *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; @@ -6035,59 +6031,48 @@ static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha) #endif } -static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile) +#if QT_CONFIG(raster_64bit) +static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) { if (coverage == 0xff000000) { // nothing - } else if (coverage == 0xffffffff && qAlpha(src) == 255) { - blend_pixel(*dst, src); - } else if (!colorProfile) { - *dst = rgbBlend(*dst, src, coverage); - } else if (*dst < 0xff000000) { - // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 - blend_pixel(*dst, src, qRgbAvg(coverage)); - } else if (srcLinear.isOpaque()) { - rgbBlendPixel(dst, coverage, srcLinear, colorProfile); + } else if (coverage == 0xffffffff) { + dest[x] = src; } else { - // First do naive blend with text-color - QRgb s = *dst; - blend_pixel(s, src); - // Then gamma-corrected blend with glyph shape - rgbBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); + QRgba64 dstColor = dest[x]; + if (dstColor.isOpaque()) { + if (colorProfile) + dstColor = colorProfile->toLinear(dstColor); + dstColor = rgbBlend(dstColor, srcLinear, coverage); + if (colorProfile) + dstColor = colorProfile->fromLinear(dstColor); + dest[x] = dstColor; + } else { + // Do a gray alphablend. + alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); + } } } +#endif -#if QT_CONFIG(raster_64bit) -static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile) -{ - // Do a gammacorrected RGB alphablend... - const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst; - - QRgba64 blend = rgbBlend(dlinear, slinear, coverage); - - dst = colorProfile ? colorProfile->fromLinear(blend) : blend; -} - -static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) +static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile) { if (coverage == 0xff000000) { // nothing } else if (coverage == 0xffffffff) { - blend_pixel(dest[x], src); - } else if (!dest[x].isOpaque()) { - // Do a gray alphablend. - alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); - } else if (src.isOpaque()) { - rgbBlendPixel(dest[x], coverage, srcLinear, colorProfile); - } else { - // First do naive blend with text-color - QRgba64 s = dest[x]; - blend_pixel(s, src); - // Then gamma-corrected blend with glyph shape - rgbBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); + *dst = src; + } else if (*dst < 0xff000000) { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + const int a = qRgbAvg(coverage); + *dst = INTERPOLATE_PIXEL_255(src, a, *dst, 255 - a); + } else if (!colorProfile) { + *dst = rgbBlend(*dst, src, coverage); + } else { + rgbBlendPixel(dst, coverage, srcLinear, colorProfile); } } +#if QT_CONFIG(raster_64bit) static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 &color, const uint *src, int mapWidth, int mapHeight, int srcStride, @@ -6102,8 +6087,12 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -6175,8 +6164,12 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } quint32 buffer[BufferSize]; const DestFetchProc destFetch = destFetchProc[rasterBuffer->format]; @@ -6249,8 +6242,12 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile && color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); + if (colorProfile) { + if (color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); + else + srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); + } if (!clip) { quint32 *dst = reinterpret_cast(rasterBuffer->scanLine(y)) + x; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index dd42b96d79..9c5d525722 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -671,8 +671,6 @@ static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src) static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src, const int const_alpha) { - if (const_alpha == 255) - return blend_pixel(dst, src); if (src != 0) { const quint32 s = BYTE_MUL(src, const_alpha); dst = s + BYTE_MUL(dst, qAlpha(~s)); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 40c822076b..87312b920a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -842,8 +842,8 @@ void QRasterPaintEngine::updateRasterState() const QPainter::CompositionMode mode = s->composition_mode; s->flags.fast_text = (s->penData.type == QSpanData::Solid) && s->intOpacity == 256 - && (mode == QPainter::CompositionMode_SourceOver - || (mode == QPainter::CompositionMode_Source + && (mode == QPainter::CompositionMode_Source + || (mode == QPainter::CompositionMode_SourceOver && s->penData.solidColor.isOpaque())); } diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h index d145dbfbea..ca879de27c 100644 --- a/src/gui/painting/qrgba64_p.h +++ b/src/gui/painting/qrgba64_p.h @@ -284,8 +284,6 @@ static Q_ALWAYS_INLINE void blend_pixel(QRgba64 &dst, QRgba64 src) static Q_ALWAYS_INLINE void blend_pixel(QRgba64 &dst, QRgba64 src, const int const_alpha) { - if (const_alpha == 255) - return blend_pixel(dst, src); if (!src.isTransparent()) { src = multiplyAlpha255(src, const_alpha); dst = src + multiplyAlpha65535(dst, 65535 - src.alpha()); -- 2.23.0