summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qguiapplication.cpp1
-rw-r--r--src/gui/kernel/qplatformwindow.cpp8
-rw-r--r--src/gui/kernel/qplatformwindow.h1
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp17
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h4
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h5
-rw-r--r--src/gui/painting/qbackingstore.cpp3
-rw-r--r--src/gui/painting/qblendfunctions.cpp187
-rw-r--r--src/gui/painting/qdrawhelper.cpp67
-rw-r--r--src/gui/painting/qdrawhelper_p.h29
-rw-r--r--src/gui/painting/qrgba64.h117
-rw-r--r--src/gui/text/qfontengine_ft.cpp31
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp19
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 &region)
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;