From ab059940aad327b7dbe7ef22cfd061061feb6e0e Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 4 May 2017 14:41:42 +0200 Subject: Revert gamma-corrected handling of transparent destination buffer Due to the text blend routines being used by ARGB32 and due to another bug on invalid premultiplied buffers, we need to keep using the naive blend on non-opaque pixels for now. Task-number: QTBUG-60562 Task-number: QTBUG-60571 Change-Id: Idfbb2c2e24dd840189c4fbed4e167f03bbc6ca8d Reviewed-by: Friedemann Kleint Reviewed-by: Eirik Aavitsland --- src/gui/painting/qdrawhelper.cpp | 66 ++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 37 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index b2e762a391..cb3e7523a8 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5710,17 +5710,11 @@ static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, co static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 srcLinear, const QColorProfile *colorProfile) { // Do a gammacorrected gray alphablend... - QRgba64 dstLinear = QRgba64::fromArgb32(*dst); + const QRgba64 dstLinear = colorProfile ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst); - if (colorProfile && !dstLinear.isTransparent()) - dstLinear = colorProfile->fromLinear(dstLinear.unpremultiplied()).premultiplied(); + QRgba64 blend = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage); - dstLinear = interpolate255(srcLinear, coverage, dstLinear, 255 - coverage); - - if (colorProfile && !dstLinear.isTransparent()) - dstLinear = colorProfile->fromLinear(dstLinear.unpremultiplied()).premultiplied(); - - *dst = toArgb32(dstLinear); + *dst = colorProfile ? colorProfile->fromLinear64(blend) : toArgb32(blend); } static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcLinear, quint32 src, const QColorProfile *colorProfile) @@ -5730,7 +5724,12 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL } else if (coverage == 255) { *dst = src; } else { - grayBlendPixel(dst, coverage, srcLinear, 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); + } } } @@ -5818,14 +5817,25 @@ static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, co dstColor = colorProfile->fromLinear(dstColor); dest[x] = dstColor; } else { - // Give up and do a gray alphablend. - if (colorProfile && !dstColor.isTransparent()) - dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); + // Do a gray alphablend. + alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); + } + } +} + +static inline void alphargbblend_argb32(quint32 *dst, uint coverage, QRgba64 srcLinear, quint32 src, const QColorProfile *colorProfile) +{ + if (coverage == 0xff000000) { + // nothing + } else if (coverage == 0xffffffff) { + *dst = src; + } else { + if (*dst >= 0xff000000) { + rgbBlendPixel(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 const int a = qRgbAvg(coverage); - dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - a); - if (colorProfile && !dstColor.isTransparent()) - dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); - dest[x] = dstColor; + *dst = INTERPOLATE_PIXEL_255(src, a, *dst, 255 - a); } } } @@ -5930,16 +5940,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, while (mapHeight--) { for (int i = 0; i < mapWidth; ++i) { const uint coverage = src[i]; - if (coverage == 0xffffffff) { - dst[i] = c; - } else if (coverage != 0xff000000) { - if (dst[i] >= 0xff000000) { - rgbBlendPixel(dst + i, coverage, srcColor, colorProfile); - } else { - // Give up and do a gray blend. - grayBlendPixel(dst + i, qRgbAvg(coverage), srcColor, colorProfile); - } - } + alphargbblend_argb32(dst + i, coverage, srcColor, c, colorProfile); } dst += destStride; @@ -5965,16 +5966,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, for (int xp=start; xp= 0xff000000) { - rgbBlendPixel(dst + xp, coverage, srcColor, colorProfile); - } else { - // Give up and do a gray blend. - grayBlendPixel(dst + xp, qRgbAvg(coverage), srcColor, colorProfile); - } - } + alphargbblend_argb32(dst + xp, coverage, srcColor, c, colorProfile); } } // for (i -> line.count) src += srcStride; -- cgit v1.2.3 From 07fd674740b4f80c45c84ad88659f0c4889943e5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 20 Apr 2017 10:01:05 +0200 Subject: Fix painterpath rect intersections with points on the rect QPainterPath could in certain cases where sub-path points were on the border of a rect fail to calculate intersects() correctly. The patch adds handling of such cases by looking if end points cross in or out of the rect. Other cases are already caught. Task-number: QTBUG-31551 Change-Id: I6284da8ff8646d4636702923a76362302dde5767 Reviewed-by: Eirik Aavitsland --- src/gui/painting/qpainterpath.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 7dbc83b338..27bd2e59e6 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1981,6 +1981,17 @@ static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qr return false; } +static bool pointOnEdge(const QRectF &rect, const QPointF &point) +{ + if ((point.x() == rect.left() || point.x() == rect.right()) && + (point.y() >= rect.top() && point.y() <= rect.bottom())) + return true; + if ((point.y() == rect.top() || point.y() == rect.bottom()) && + (point.x() >= rect.left() && point.x() <= rect.right())) + return true; + return false; +} + /* Returns \c true if any lines or curves cross the four edges in of rect */ @@ -1988,6 +1999,7 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF { QPointF last_pt; QPointF last_start; + enum { OnRect, InsideRect, OutsideRect} edgeStatus = OnRect; for (int i=0; ielementCount(); ++i) { const QPainterPath::Element &e = path->elementAt(i); @@ -2026,6 +2038,27 @@ static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF default: break; } + // Handle crossing the edges of the rect at the end-points of individual sub-paths. + // A point on on the edge itself is considered neither inside nor outside for this purpose. + if (!pointOnEdge(rect, last_pt)) { + bool contained = rect.contains(last_pt); + switch (edgeStatus) { + case OutsideRect: + if (contained) + return true; + break; + case InsideRect: + if (!contained) + return true; + break; + case OnRect: + edgeStatus = contained ? InsideRect : OutsideRect; + break; + } + } else { + if (last_pt == last_start) + edgeStatus = OnRect; + } } // implicitly close last subpath -- cgit v1.2.3