From 8f760808e0fe0fe6dd89d561f118b19ed8085e7a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 6 May 2015 14:23:57 +0200 Subject: Fix premul conversion from ARGB32 to A2RGB30 formats. When a premultiplied alpha changes value because it is rounded to fewer bits the premultiplied colors may need to be recalculated with the new value. Otherwise the color will both be wrong and potentially invalid. Change-Id: I9ec74a22aac73cd7ffab04e180cf2bf35bb4c315 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 10 ++++++-- src/gui/painting/qdrawhelper_p.h | 17 +++++++++++++ src/gui/painting/qdrawhelper_sse4.cpp | 16 ++++++++++++ src/gui/painting/qdrawingprimitive_sse2_p.h | 38 +++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index d34b2b9a44..d74b48a3ca 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6640,6 +6640,10 @@ void qt_memfill32(quint32 *dest, quint32 color, int count) } #endif +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 +template const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); +#endif + void qInitDrawhelperAsm() { CompositionFunction *functionForModeAsm = 0; @@ -6704,7 +6708,7 @@ void qInitDrawhelperAsm() } #endif // SSSE3 -#if QT_COMPILER_SUPPORTS_SSE4_1 +#if defined(QT_COMPILER_SUPPORTS_SSE4_1) if (qCpuHasFeature(SSE4_1)) { #if !defined(__SSE4_1__) extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); @@ -6718,10 +6722,12 @@ void qInitDrawhelperAsm() qPixelLayouts[QImage::Format_ARGB32].convertFromARGB32PM = convertARGB32FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBA8888].convertFromARGB32PM = convertRGBA8888FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBX8888].convertFromARGB32PM = convertRGBXFromARGB32PM_sse4; + qPixelLayouts[QImage::Format_A2BGR30_Premultiplied].convertFromARGB32PM = convertA2RGB30PMFromARGB32PM_sse4; + qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].convertFromARGB32PM = convertA2RGB30PMFromARGB32PM_sse4; } #endif -#if QT_COMPILER_SUPPORTS_AVX2 && !defined(__AVX2__) +#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__) if (qCpuHasFeature(AVX2)) { extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 66ef5949d9..73ff21812a 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -847,9 +847,25 @@ template inline uint qConvertRgb32ToRgb30(QRgb); template inline QRgb qConvertA2rgb30ToArgb32(uint c); +// A combined unpremultiply and premultiply with new simplified alpha. +// Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30). +template +inline QRgb qRepremultiply(QRgb p) +{ + const uint alpha = qAlpha(p); + if (alpha == 255 || alpha == 0) + return p; + p = qUnpremultiply(p); + Q_CONSTEXPR uint mult = 255 / (255 >> Shift); + const uint newAlpha = mult * (alpha >> Shift); + p = (p & ~0xff000000) | (newAlpha<<24); + return qPremultiply(p); +} + template<> inline uint qConvertArgb32ToA2rgb30(QRgb c) { + c = qRepremultiply<6>(c); return (c & 0xc0000000) | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000)) | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) @@ -859,6 +875,7 @@ inline uint qConvertArgb32ToA2rgb30(QRgb c) template<> inline uint qConvertArgb32ToA2rgb30(QRgb c) { + c = qRepremultiply<6>(c); return (c & 0xc0000000) | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000)) | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00)) diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp index 43a3958997..7cc498eefc 100644 --- a/src/gui/painting/qdrawhelper_sse4.cpp +++ b/src/gui/painting/qdrawhelper_sse4.cpp @@ -74,6 +74,22 @@ const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *s return buffer; } +template +const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qConvertArgb32ToA2rgb30_sse4(src[i]); + return buffer; +} + +template +const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *); +template +const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *); + QT_END_NAMESPACE #endif diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h index 1a7dddf0d5..c74055e440 100644 --- a/src/gui/painting/qdrawingprimitive_sse2_p.h +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -35,6 +35,7 @@ #define QDRAWINGPRIMITIVE_SSE2_P_H #include +#include "qdrawhelper_p.h" #ifdef __SSE2__ @@ -256,6 +257,43 @@ inline QRgb qUnpremultiply_sse4(QRgb p) vl = _mm_packus_epi16(vl, vl); return _mm_cvtsi128_si32(vl); } + +template +QT_FUNCTION_TARGET(SSE4_1) +inline uint qConvertArgb32ToA2rgb30_sse4(QRgb p) +{ + const uint alpha = qAlpha(p); + if (alpha == 255) + return qConvertRgb32ToRgb30(p); + if (alpha == 0) + return 0; + Q_CONSTEXPR uint mult = 255 / (255 >> 6); + const uint invAlpha = qt_inv_premul_factor[alpha]; + const uint newalpha = (alpha >> 6); + const __m128i via = _mm_set1_epi32(invAlpha); + const __m128i vna = _mm_set1_epi32(mult * newalpha); + const __m128i vr1 = _mm_set1_epi32(0x1000); + const __m128i vr2 = _mm_set1_epi32(0x80); + __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p)); + vl = _mm_mullo_epi32(vl, via); + vl = _mm_add_epi32(vl, vr1); + vl = _mm_srli_epi32(vl, 14); + vl = _mm_mullo_epi32(vl, vna); + vl = _mm_add_epi32(vl, _mm_srli_epi32(vl, 8)); + vl = _mm_add_epi32(vl, vr2); + vl = _mm_srli_epi32(vl, 8); + vl = _mm_packus_epi32(vl, vl); + uint rgb30 = (newalpha << 30); + rgb30 |= ((uint)_mm_extract_epi16(vl, 1)) << 10; + if (PixelOrder == PixelOrderRGB) { + rgb30 |= ((uint)_mm_extract_epi16(vl, 2)) << 20; + rgb30 |= ((uint)_mm_extract_epi16(vl, 0)); + } else { + rgb30 |= ((uint)_mm_extract_epi16(vl, 0)) << 20; + rgb30 |= ((uint)_mm_extract_epi16(vl, 2)); + } + return rgb30; +} #endif QT_END_NAMESPACE -- cgit v1.2.3 From 525a660ea3ea28437c6cca28cae937b71001a4e3 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 22 May 2015 11:55:50 +0200 Subject: Clarify QPainter::drawText() documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The difference between rectangle and boundingRect was not quite clear. This patch adds a snippet with a corresponding image, in order to illustrate the difference. Change-Id: Icb1fe737788cc93f1c5baa16bc0e04b8ec728f3a Reviewed-by: Topi Reiniƶ Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpainter.cpp | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 973c9da96c..213ecc5f8e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5966,8 +5966,17 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br \endtable The \a boundingRect (if not null) is set to the what the bounding rectangle - should be in order to enclose the whole text. The \a flags argument is a bitwise - OR of the following flags: + should be in order to enclose the whole text. For example, in the following + image, the dotted line represents \a boundingRect as calculated by the + function, and the dashed line represents \a rectangle: + + \table 100% + \row + \li \inlineimage qpainter-text-bounds.png + \li \snippet code/src_gui_painting_qpainter.cpp drawText + \endtable + + The \a flags argument is a bitwise OR of the following flags: \list \li Qt::AlignLeft @@ -6016,8 +6025,18 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF * \overload Draws the given \a text within the provided \a rectangle according - to the specified \a flags. The \a boundingRect (if not null) is set to - the what the bounding rectangle should be in order to enclose the whole text. + to the specified \a flags. + + The \a boundingRect (if not null) is set to the what the bounding rectangle + should be in order to enclose the whole text. For example, in the following + image, the dotted line represents \a boundingRect as calculated by the + function, and the dashed line represents \a rectangle: + + \table 100% + \row + \li \inlineimage qpainter-text-bounds.png + \li \snippet code/src_gui_painting_qpainter.cpp drawText + \endtable By default, QPainter draws text anti-aliased. @@ -6050,9 +6069,19 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF * Draws the given \a text within the rectangle with origin (\a{x}, \a{y}), \a width and \a height. - The \a boundingRect (if not null) is set to the actual bounding - rectangle of the output. The \a flags argument is a bitwise OR of - the following flags: + The \a boundingRect (if not null) is set to the what the bounding rectangle + should be in order to enclose the whole text. For example, in the following + image, the dotted line represents \a boundingRect as calculated by the + function, and the dashed line represents the rectangle defined by + \a x, \a y, \a width and \a height: + + \table 100% + \row + \li \inlineimage qpainter-text-bounds.png + \li \snippet code/src_gui_painting_qpainter.cpp drawText + \endtable + + The \a flags argument is a bitwise OR of the following flags: \list \li Qt::AlignLeft -- cgit v1.2.3 From 03fd8fa46356a70c9eabcf7ca703ddaa5e16e96f Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Mon, 8 Jun 2015 14:53:29 +0200 Subject: Further tune curveThreshold setting based on strokeWidth ad9698713f91a2e706fcd391f9806057649632ff reduced the curvethreshold for wide lines, to fix QTBUG-46151. But as a side effect, the threshold was increased for lines of widths >=0 and <4. This commit fixes that, and also adds a lance test for the issue in QTBUG-46151. Change-Id: I52507db622435fe1d2646640cb0bd9cd8222e453 Reviewed-by: Gunnar Sletta --- src/gui/painting/qstroker_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h index f967c091df..d3765bbd29 100644 --- a/src/gui/painting/qstroker_p.h +++ b/src/gui/painting/qstroker_p.h @@ -201,7 +201,7 @@ public: QStroker(); ~QStroker(); - void setStrokeWidth(qfixed width) { m_strokeWidth = width; m_curveThreshold = width >= 1 ? 1.0/width : 0.5;} + void setStrokeWidth(qfixed width) { m_strokeWidth = width; m_curveThreshold = qt_real_to_fixed(width > 4 ? 1.0/width : 0.25); } qfixed strokeWidth() const { return m_strokeWidth; } void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); } -- cgit v1.2.3 From e1b7c55a43ed62fb558cb3895865cef2b2d63fe6 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Wed, 10 Jun 2015 09:49:29 +0200 Subject: Doc: rearrange tables with overflow Task-number: QTBUG-46475 Change-Id: Id599b2eb0dee0c003475c094ad61700150e37e65 Reviewed-by: Venugopal Shivashankar --- src/gui/painting/qpainterpath.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index e2f267d7ee..48010c0a71 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -218,7 +218,7 @@ static void qt_debug_path(const QPainterPath &path) Below is a code snippet that shows how a QPainterPath object can be used: - \table 100% + \table 70% \row \li \inlineimage qpainterpath-construction.png \li -- cgit v1.2.3 From a7f2af09114cfa0996794c85bc48a601f665772d Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 28 May 2015 12:45:48 +0200 Subject: Replace MAC OS X with OS X Task-number: QTBUG-46374 Change-Id: I7bc633ab551740bd328a24b0ccae1d534af47138 Reviewed-by: Martin Smith --- src/gui/painting/qpaintengine.cpp | 6 +++--- src/gui/painting/qpainter.cpp | 2 +- src/gui/painting/qregion.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 6271c8f9e6..6ba26df3b4 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -149,7 +149,7 @@ QFont QTextItem::font() const provided is the raster paint engine, which contains a software rasterizer which supports the full feature set on all supported platforms. This is the default for painting on QWidget-based classes in e.g. on Windows, - X11 and Mac OS X, it is the backend for painting on QImage and it is + X11 and OS X, it is the backend for painting on QImage and it is used as a fallback for paint engines that do not support a certain capability. In addition we provide QPaintEngine implementations for OpenGL (accessible through QGLWidget) and printing (which allows using @@ -363,8 +363,8 @@ void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDraw \value X11 \value Windows \value MacPrinter - \value CoreGraphics Mac OS X's Quartz2D (CoreGraphics) - \value QuickDraw Mac OS X's QuickDraw + \value CoreGraphics OS X's Quartz2D (CoreGraphics) + \value QuickDraw OS X's QuickDraw \value QWindowSystem Qt for Embedded Linux \value PostScript (No longer supported) \value OpenGL diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 213ecc5f8e..20608e5aee 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6206,7 +6206,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) QPen wavePen = pen; wavePen.setCapStyle(Qt::SquareCap); - // This is to protect against making the line too fat, as happens on Mac OS X + // This is to protect against making the line too fat, as happens on OS X // due to it having a rather thick width for the regular underline. const qreal maxPenWidth = .8 * radius; if (wavePen.widthF() > maxPenWidth) diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 19314ef84f..e6b777a30e 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -906,7 +906,7 @@ QRegion QRegion::intersect(const QRect &r) const sort key and X as the minor sort key. \endlist \omit - Only some platforms have these restrictions (Qt for Embedded Linux, X11 and Mac OS X). + Only some platforms have these restrictions (Qt for Embedded Linux, X11 and OS X). \endomit */ -- cgit v1.2.3 From 49049d90470eb3e94bda77d19ab7f7c57a0bd57f Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Jun 2015 11:22:32 +0200 Subject: Fix simple semi-transparent blending of RGB32 on RGB30 We can not rely on the alpha being preserved as part of the source when the source is converted to a2rgb30 which has much less alpha accuracy instead we need to apply the alpha on the result. Change-Id: Iac3104666980825e44ed3490370cdbe21dc68008 Reviewed-by: Gunnar Sletta --- src/gui/painting/qblendfunctions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gui/painting') diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index b3710411c9..dbdd82e432 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -422,8 +422,8 @@ static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl, const_alpha = (const_alpha * 255) >> 8; for (int y=0; y(s) + BYTE_MUL_RGB30(dst[x], 255 - qAlpha(s)); + uint s = src[x]; + dst[x] = BYTE_MUL_RGB30(qConvertArgb32ToA2rgb30(s), const_alpha) + BYTE_MUL_RGB30(dst[x], 255 - qt_div_255(qAlpha(s) * const_alpha)); } dst = (quint32 *)(((uchar *) dst) + dbpl); src = (const quint32 *)(((const uchar *) src) + sbpl); -- cgit v1.2.3