diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 1 | ||||
-rw-r--r-- | src/gui/kernel/qplatformwindow.cpp | 8 | ||||
-rw-r--r-- | src/gui/kernel/qplatformwindow.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 17 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_p.h | 5 | ||||
-rw-r--r-- | src/gui/painting/qbackingstore.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qblendfunctions.cpp | 187 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 67 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 29 | ||||
-rw-r--r-- | src/gui/painting/qrgba64.h | 117 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 31 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft_p.h | 3 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 19 |
14 files changed, 203 insertions, 289 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f240153f9f..5e2a5b86a4 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1935,6 +1935,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE } } #endif + e->eventAccepted = ev.isAccepted(); } void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index d10bd1e9eb..0430d5a4c6 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -690,6 +690,14 @@ QRect QPlatformWindow::windowGeometry() const } /*! + Returns the QWindow frame geometry. +*/ +QRect QPlatformWindow::windowFrameGeometry() const +{ + return QHighDpi::toNativePixels(window()->frameGeometry(), window()); +} + +/*! Returns the closest acceptable geometry for a given geometry before a resize/move event for platforms that support it, for example to implement heightForWidth(). diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 692ae862db..1b283dbb4f 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -138,6 +138,7 @@ public: QSize windowBaseSize() const; QSize windowSizeIncrement() const; QRect windowGeometry() const; + QRect windowFrameGeometry() const; QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const; protected: diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3ab2f59661..88cf2dac93 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -303,24 +303,24 @@ bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, ulong ti } -void QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { +bool QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleKeyEvent(w, time, t, k, mods, text, autorep, count); + return handleKeyEvent(w, time, t, k, mods, text, autorep, count); } -void QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) +bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for // shortcut overriding on other platforms. #if defined(Q_OS_OSX) if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(tlw, timestamp, k, mods, text)) - return; + return true; #endif // Q_OS_OSX QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, @@ -441,10 +441,12 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e windowSystemEventQueue.remove(event); } -void QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) +bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) { + bool accepted = true; if (synchronousWindowSystemEvents) { QGuiApplicationPrivate::processWindowSystemEvent(ev); + accepted = ev->eventAccepted; delete ev; } else { windowSystemEventQueue.append(ev); @@ -452,6 +454,7 @@ void QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfa if (dispatcher) dispatcher->wakeUp(); } + return accepted; } void QWindowSystemInterface::registerTouchDevice(QTouchDevice *device) @@ -611,7 +614,7 @@ void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::Process Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread()); QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex); - flushWindowSystemEvents(flags); + sendWindowSystemEvents(flags); QWindowSystemInterfacePrivate::eventsFlushed.wakeOne(); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 453dbe81cf..ace1a4fe24 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -95,8 +95,8 @@ public: quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString & text = QString(), bool autorep = false, ushort count = 1); - static void handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); - static void handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); static void handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index cbc3bad7cd..cc0ca6bf81 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -101,7 +101,7 @@ public: }; explicit WindowSystemEvent(EventType t) - : type(t), flags(0) { } + : type(t), flags(0), eventAccepted(true) { } virtual ~WindowSystemEvent() { } bool synthetic() const { return flags & Synthetic; } @@ -109,6 +109,7 @@ public: EventType type; int flags; + bool eventAccepted; }; class CloseEvent : public WindowSystemEvent { @@ -480,7 +481,7 @@ public: static WindowSystemEvent *getNonUserInputWindowSystemEvent(); static WindowSystemEvent *peekWindowSystemEvent(EventType t); static void removeWindowSystemEvent(WindowSystemEvent *event); - static void handleWindowSystemEvent(WindowSystemEvent *ev); + static bool handleWindowSystemEvent(WindowSystemEvent *ev); static QElapsedTimer eventTime; static bool synchronousWindowSystemEvents; diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 68ed3eae6e..8a5a6d4fcf 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -182,7 +182,8 @@ void QBackingStore::beginPaint(const QRegion ®ion) qCDebug(lcScaling) << "QBackingStore::beginPaint new backingstore for" << d_ptr->window; qCDebug(lcScaling) << " source size" << source->size() << "dpr" << source->devicePixelRatio(); d_ptr->highDpiBackingstore.reset( - new QImage(source->bits(), source->width(), source->height(), source->format())); + new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format())); + qreal targetDevicePixelRatio = d_ptr->window->devicePixelRatio(); d_ptr->highDpiBackingstore->setDevicePixelRatio(targetDevicePixelRatio); qCDebug(lcScaling) <<" destination size" << d_ptr->highDpiBackingstore->size() diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index dbdd82e432..0898a20998 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -395,169 +395,6 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, } } -template<QtPixelOrder PixelOrder> -static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - fprintf(stdout, "qt_blend_argb32pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - fflush(stdout); -#endif - - const uint *src = (const uint *) srcPixels; - uint *dst = (uint *) destPixels; - if (const_alpha == 256) { - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint s = src[x]; - dst[x] = qConvertArgb32ToA2rgb30<PixelOrder>(s) + BYTE_MUL_RGB30(dst[x], 255 - qAlpha(s)); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } else if (const_alpha != 0) { - const_alpha = (const_alpha * 255) >> 8; - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint s = src[x]; - dst[x] = BYTE_MUL_RGB30(qConvertArgb32ToA2rgb30<PixelOrder>(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); - } - } -} - -template<QtPixelOrder PixelOrder> -static void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - fprintf(stdout, "qt_blend_rgb32_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - fflush(stdout); -#endif - - if (const_alpha != 256) { - qt_blend_argb32pm_on_a2rgb30pm<PixelOrder>(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - return; - } - - const uint *src = (const uint *) srcPixels; - uint *dst = (uint *) destPixels; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - dst[x] = qConvertRgb32ToRgb30<PixelOrder>(src[x]); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } -} - -static void qt_blend_a2rgb30pm_on_a2rgb30pm(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - fprintf(stdout, "qt_blend_a2rgb30pm_on_a2rgb30pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - fflush(stdout); -#endif - - const uint *src = (const uint *) srcPixels; - uint *dst = (uint *) destPixels; - if (const_alpha == 256) { - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint s = src[x]; - dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s)); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } else if (const_alpha != 0) { - const uint const_alpha255 = (const_alpha * 255) >> 8; - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8; - uint s = BYTE_MUL_RGB30(src[x], const_alpha255); - dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - a); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } -} - - -static void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - fprintf(stdout, "qt_blend_rgb30_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - fflush(stdout); -#endif - - if (const_alpha != 256) { - qt_blend_a2rgb30pm_on_a2rgb30pm(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - return; - } - - const uint *src = (const uint *) srcPixels; - uint *dst = (uint *) destPixels; - int len = w * 4; - for (int y=0; y<h; ++y) { - memcpy(dst, src, len); - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } -} - -static void qt_blend_a2bgr30pm_on_a2rgb30pm(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - fprintf(stdout, "qt_blend_a2bgr30pm_on_a2rgb32pm: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); - fflush(stdout); -#endif - - const uint *src = (const uint *) srcPixels; - uint *dst = (uint *) destPixels; - if (const_alpha == 256) { - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint s = qRgbSwapRgb30(src[x]); - dst[x] = s + BYTE_MUL_RGB30(dst[x], 255 - qAlphaRgb30(s)); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } else if (const_alpha != 0) { - const uint const_alpha255 = (const_alpha * 255) >> 8; - for (int y=0; y<h; ++y) { - for (int x=0; x<w; ++x) { - uint a = (qAlphaRgb30(src[x]) * const_alpha) >> 8; - uint s = BYTE_MUL_RGB30(src[x], const_alpha255); - dst[x] = qRgbSwapRgb30(s) + BYTE_MUL_RGB30(dst[x], 255 - a); - } - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } -} - struct Blend_RGB32_on_RGB32_NoAlpha { inline void write(quint32 *dst, quint32 src) { *dst = src; } @@ -772,30 +609,6 @@ void qInitBlendFunctions() qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32; qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32; #endif - qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>; - qBlendFunctions[QImage::Format_BGR30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>; - qBlendFunctions[QImage::Format_BGR30][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30; - qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30; - qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30; - qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm; qTransformFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32; qTransformFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 07e5a3d19b..0cf7e20605 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -1252,25 +1252,54 @@ static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *b const __m128i cmask = _mm_set1_epi32(0x000003ff); int i = 0; __m128i vr, vg, vb, va; - for (; i < count-1; i += 2) { - __m128i vs = _mm_loadu_si128((const __m128i*)buffer); - buffer += 2; - vr = _mm_srli_epi64(vs, 6); - vg = _mm_srli_epi64(vs, 16 + 6 - 10); - vb = _mm_srli_epi64(vs, 32 + 6); - vr = _mm_and_si128(vr, cmask); - vg = _mm_and_si128(vg, gmask); - vb = _mm_and_si128(vb, cmask); - va = _mm_srli_epi64(vs, 48 + 14); - if (PixelOrder == PixelOrderRGB) - vr = _mm_slli_epi32(vr, 20); - else - vb = _mm_slli_epi32(vb, 20); - va = _mm_slli_epi32(va, 30); - __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va)); - vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0)); - _mm_storel_epi64((__m128i*)dest, vd); - dest += 2; + if (i < count && (const uintptr_t)buffer & 0x8) { + *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++); + ++i; + } + + for (; i < count-15; i += 16) { + // Repremultiplying is really expensive and hard to do in SIMD without AVX2, + // so we try to avoid it by checking if it is needed 16 samples at a time. + __m128i vOr = _mm_set1_epi32(0); + __m128i vAnd = _mm_set1_epi32(0xffffffff); + for (int j = 0; j < 16; j += 2) { + __m128i vs = _mm_load_si128((const __m128i*)(buffer + j)); + vOr = _mm_or_si128(vOr, vs); + vAnd = _mm_and_si128(vAnd, vs); + } + const quint16 orAlpha = ((uint)_mm_extract_epi16(vOr, 3)) | ((uint)_mm_extract_epi16(vOr, 7)); + const quint16 andAlpha = ((uint)_mm_extract_epi16(vAnd, 3)) & ((uint)_mm_extract_epi16(vAnd, 7)); + + if (andAlpha == 0xffff) { + for (int j = 0; j < 16; j += 2) { + __m128i vs = _mm_load_si128((const __m128i*)buffer); + buffer += 2; + vr = _mm_srli_epi64(vs, 6); + vg = _mm_srli_epi64(vs, 16 + 6 - 10); + vb = _mm_srli_epi64(vs, 32 + 6); + vr = _mm_and_si128(vr, cmask); + vg = _mm_and_si128(vg, gmask); + vb = _mm_and_si128(vb, cmask); + va = _mm_srli_epi64(vs, 48 + 14); + if (PixelOrder == PixelOrderRGB) + vr = _mm_slli_epi32(vr, 20); + else + vb = _mm_slli_epi32(vb, 20); + va = _mm_slli_epi32(va, 30); + __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va)); + vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0)); + _mm_storel_epi64((__m128i*)dest, vd); + dest += 2; + } + } else if (orAlpha == 0) { + for (int j = 0; j < 16; ++j) { + *dest++ = 0; + buffer++; + } + } else { + for (int j = 0; j < 16; ++j) + *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++); + } } for (; i < count; ++i) diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 2c222b97c2..2fb9e7760c 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -62,15 +62,12 @@ QT_BEGIN_NAMESPACE #if defined(Q_CC_GNU) # define Q_STATIC_TEMPLATE_FUNCTION static -# define Q_ALWAYS_INLINE inline __attribute__((always_inline)) # define Q_DECL_RESTRICT __restrict__ #elif defined(Q_CC_MSVC) # define Q_STATIC_TEMPLATE_FUNCTION static -# define Q_ALWAYS_INLINE __forceinline # define Q_DECL_RESTRICT __restrict #else # define Q_STATIC_TEMPLATE_FUNCTION static -# define Q_ALWAYS_INLINE inline # define Q_DECL_RESTRICT #endif @@ -712,18 +709,6 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { 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; - uint xr = (x >> 20) & 0x3ff; - uint xg = (x >> 10) & 0x3ff; - uint xb = x & 0x3ff; - xa = qt_div_255(xa * a); - xr = qt_div_255(xr * a); - xg = qt_div_255(xg * a); - xb = qt_div_255(xb * a); - return (xa << 30) | (xr << 20) | (xg << 10) | xb; -} - static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c) { uint a = c >> 30; @@ -897,6 +882,18 @@ inline QRgb qRepremultiply(QRgb p) return qPremultiply(p); } +template<unsigned int Shift> +inline QRgba64 qRepremultiply(QRgba64 p) +{ + const uint alpha = p.alpha(); + if (alpha == 65535 || alpha == 0) + return p; + p = p.unpremultiplied(); + Q_CONSTEXPR uint mult = 65535 / (65535 >> Shift); + p.setAlpha(mult * (alpha >> Shift)); + return p.premultiplied(); +} + template<> inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c) { @@ -1000,6 +997,7 @@ template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64); template<> inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) { + c = qRepremultiply<14>(c); const uint a = c.alpha() >> 14; const uint r = c.red() >> 6; const uint g = c.green() >> 6; @@ -1010,6 +1008,7 @@ inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) template<> inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c) { + c = qRepremultiply<14>(c); const uint a = c.alpha() >> 14; const uint r = c.red() >> 6; const uint g = c.green() >> 6; diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index 290501047d..b701b224be 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -40,35 +40,43 @@ QT_BEGIN_NAMESPACE class QRgba64 { - struct qrgba_t { - quint16 red; - quint16 green; - quint16 blue; - quint16 alpha; + quint64 rgba; + + // Make sure that the representation always has the order: red green blue alpha, independent + // of byte order. This way, vector operations that assume 4 16-bit values see the correct ones. + enum { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + RedShift = 48, + GreenShift = 32, + BlueShift = 16, + AlphaShift = 0 +#else // little endian: + RedShift = 0, + GreenShift = 16, + BlueShift = 32, + AlphaShift = 48 +#endif }; - union { - struct qrgba_t c; - quint64 rgba; - }; public: // No constructors are allowed, since this needs to be usable in a union in no-c++11 mode. // When c++11 is mandatory, we can add all but a copy constructor. - Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) + Q_DECL_RELAXED_CONSTEXPR static + QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) { QRgba64 rgba64 #ifdef Q_COMPILER_UNIFORM_INIT = {} #endif ; - - rgba64.c.red = red; - rgba64.c.green = green; - rgba64.c.blue = blue; - rgba64.c.alpha = alpha; + rgba64.rgba = quint64(red) << RedShift + | quint64(green) << GreenShift + | quint64(blue) << BlueShift + | quint64(alpha) << AlphaShift; return rgba64; } - Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba64(quint64 c) + Q_DECL_RELAXED_CONSTEXPR static + QRgba64 fromRgba64(quint64 c) { QRgba64 rgba64 #ifdef Q_COMPILER_UNIFORM_INIT @@ -85,42 +93,49 @@ public: rgb64.rgba |= rgb64.rgba << 8; return rgb64; } - Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromArgb32(uint rgb) + Q_DECL_RELAXED_CONSTEXPR static + QRgba64 fromArgb32(uint rgb) { 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; } - Q_DECL_CONSTEXPR quint16 alpha() const { return c.alpha; } - void setRed(quint16 _red) { c.red = _red; } - void setGreen(quint16 _green) { c.green = _green; } - void setBlue(quint16 _blue) { c.blue = _blue; } - void setAlpha(quint16 _alpha) { c.alpha = _alpha; } - - Q_DECL_CONSTEXPR quint8 red8() const { return div_257(c.red); } - Q_DECL_CONSTEXPR quint8 green8() const { return div_257(c.green); } - Q_DECL_CONSTEXPR quint8 blue8() const { return div_257(c.blue); } - Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(c.alpha); } + Q_DECL_CONSTEXPR bool isOpaque() const + { + return (rgba & alphaMask()) == alphaMask(); + } + Q_DECL_CONSTEXPR bool isTransparent() const + { + return (rgba & alphaMask()) == 0; + } + + Q_DECL_CONSTEXPR quint16 red() const { return rgba >> RedShift; } + Q_DECL_CONSTEXPR quint16 green() const { return rgba >> GreenShift; } + Q_DECL_CONSTEXPR quint16 blue() const { return rgba >> BlueShift; } + Q_DECL_CONSTEXPR quint16 alpha() const { return rgba >> AlphaShift; } + void setRed(quint16 _red) { *this = fromRgba64(_red, green(), blue(), alpha()); } + void setGreen(quint16 _green) { *this = fromRgba64(red(), _green, blue(), alpha()); } + void setBlue(quint16 _blue) { *this = fromRgba64(red(), green(), _blue, alpha()); } + void setAlpha(quint16 _alpha) { *this = fromRgba64(red(), green(), blue(), _alpha); } + + Q_DECL_CONSTEXPR quint8 red8() const { return div_257(red()); } + Q_DECL_CONSTEXPR quint8 green8() const { return div_257(green()); } + Q_DECL_CONSTEXPR quint8 blue8() const { return div_257(blue()); } + Q_DECL_CONSTEXPR quint8 alpha8() const { return div_257(alpha()); } Q_DECL_CONSTEXPR uint toArgb32() const { return (alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8(); } Q_DECL_CONSTEXPR ushort toRgb16() const { - return (c.red & 0xf800) | ((c.green >> 10) << 5) | (c.blue >> 11); + return (red() & 0xf800) | ((green() >> 10) << 5) | (blue() >> 11); } Q_DECL_RELAXED_CONSTEXPR QRgba64 premultiplied() const { - const quint32 a = c.alpha; - const quint16 r = div_65535(c.red * a); - const quint16 g = div_65535(c.green * a); - const quint16 b = div_65535(c.blue * a); + const quint32 a = alpha(); + const quint16 r = div_65535(red() * a); + const quint16 g = div_65535(green() * a); + const quint16 b = div_65535(blue() * a); return fromRgba64(r, g, b, a); } @@ -145,27 +160,31 @@ public: } private: + static Q_DECL_CONSTEXPR quint64 alphaMask() { return quint64(0xffff) << AlphaShift; } + 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); } static Q_DECL_CONSTEXPR uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_32bit() const { - if (c.alpha == 0xffff || c.alpha == 0) + const quint16 a = alpha(); + if (a == 0xffff || a == 0) return *this; - const quint16 r = (quint32(c.red) * 0xffff + c.alpha/2) / c.alpha; - const quint16 g = (quint32(c.green) * 0xffff + c.alpha/2) / c.alpha; - const quint16 b = (quint32(c.blue) * 0xffff + c.alpha/2) / c.alpha; - return fromRgba64(r, g, b, c.alpha); + const quint16 r = (quint32(red()) * 0xffff + a/2) / a; + const quint16 g = (quint32(green()) * 0xffff + a/2) / a; + const quint16 b = (quint32(blue()) * 0xffff + a/2) / a; + return fromRgba64(r, g, b, a); } Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_64bit() const { - if (c.alpha == 0xffff || c.alpha == 0) + const quint16 a = alpha(); + if (a == 0xffff || a == 0) return *this; - const quint64 fa = (Q_UINT64_C(0xffff00008000) + c.alpha/2) / c.alpha; - const quint16 r = (c.red * fa + 0x80000000) >> 32; - const quint16 g = (c.green * fa + 0x80000000) >> 32; - const quint16 b = (c.blue * fa + 0x80000000) >> 32; - return fromRgba64(r, g, b, c.alpha); + const quint64 fa = (Q_UINT64_C(0xffff00008000) + a/2) / a; + const quint16 r = (red() * fa + 0x80000000) >> 32; + const quint16 g = (green() * fa + 0x80000000) >> 32; + const quint16 b = (blue() * fa + 0x80000000) >> 32; + return fromRgba64(r, g, b, a); } }; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 37be0afccf..246df127ad 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -99,6 +99,13 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; +static const QFontEngine::HintStyle ftInitialDefaultHintStyle = +#ifdef Q_OS_WIN + QFontEngineFT::HintFull; +#else + QFontEngineFT::HintNone; +#endif + // -------------------------- Freetype support ------------------------------ class QtFreetypeData @@ -629,11 +636,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) antialias = true; freetype = 0; default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; -#ifndef Q_OS_WIN - default_hint_style = HintNone; -#else - default_hint_style = HintFull; -#endif + default_hint_style = ftInitialDefaultHintStyle; subpixelType = Subpixel_None; lcdFilterType = 0; #if defined(FT_LCD_FILTER_H) @@ -760,6 +763,24 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, return true; } +void QFontEngineFT::setQtDefaultHintStyle(QFont::HintingPreference hintingPreference) +{ + switch (hintingPreference) { + case QFont::PreferNoHinting: + setDefaultHintStyle(HintNone); + break; + case QFont::PreferFullHinting: + setDefaultHintStyle(HintFull); + break; + case QFont::PreferVerticalHinting: + setDefaultHintStyle(HintLight); + break; + case QFont::PreferDefaultHinting: + setDefaultHintStyle(ftInitialDefaultHintStyle); + break; + } +} + void QFontEngineFT::setDefaultHintStyle(HintStyle style) { default_hint_style = style; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 7b28a4064f..b81e51bf2e 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -281,7 +281,7 @@ private: virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE; - + void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference); virtual void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE; virtual QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; @@ -307,6 +307,7 @@ private: friend class QFontEngineFTRawFont; friend class QFontconfigDatabase; friend class QBasicFontDatabase; + friend class QCoreTextFontDatabase; friend class QFontEngineMultiFontConfig; int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index d2174c5e06..6b98c14205 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1120,6 +1120,15 @@ QT_BEGIN_INCLUDE_NAMESPACE QT_END_INCLUDE_NAMESPACE +#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE) +static const char *s_shapersForOsxFreeType[] = +{ + "ot", + "fallback", + Q_NULLPTR +}; +#endif + int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const { uint glyphs_shaped = 0; @@ -1172,7 +1181,15 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st }; const int num_features = 1; - bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0); + const char *const *shaper_list = Q_NULLPTR; +#if defined(Q_OS_OSX) && !defined(QT_NO_FREETYPE) + // What's behind QFontEngine::FaceData::user_data isn't compatible between CoreText and + // FreeType font engines - specifically functions in hb-coretext.cc would run into undefined + // behavior with data from the FreeType engine. The OpenType shaper works with that engine. + if (actualFontEngine->type() == QFontEngine::Freetype) + shaper_list = s_shapersForOsxFreeType; +#endif + bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list); if (Q_UNLIKELY(!shapedOk)) { hb_buffer_destroy(buffer); return 0; |