diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-08-19 00:29:51 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-08-19 00:29:51 (GMT) |
commit | e5893ababec6c58207c8066908e21bff3d746356 (patch) | |
tree | b4800e3a1fd5fa209b39e2f2d627081ed72bed38 /src/gui | |
parent | 2abbc5fc400dfa8ad26397cc39f49f9b3a4304c9 (diff) | |
parent | ceb068261e326f38b4049becd75c7160a6b84f87 (diff) | |
download | Qt-e5893ababec6c58207c8066908e21bff3d746356.zip Qt-e5893ababec6c58207c8066908e21bff3d746356.tar.gz Qt-e5893ababec6c58207c8066908e21bff3d746356.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/egl/qegl_x11.cpp | 2 | ||||
-rw-r--r-- | src/gui/itemviews/qabstractitemview.cpp | 8 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 67 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 7 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 61 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_mac.mm | 18 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 17 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/painting.pri | 1 | ||||
-rw-r--r-- | src/gui/painting/qbackingstore.cpp | 9 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 11 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_ssse3.cpp | 253 | ||||
-rw-r--r-- | src/gui/painting/qgrayraster.c | 80 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_x11.cpp | 8 | ||||
-rw-r--r-- | src/gui/painting/qwindowsurface_qws.cpp | 6 | ||||
-rw-r--r-- | src/gui/text/qtextobject.cpp | 4 | ||||
-rw-r--r-- | src/gui/util/qcompleter.cpp | 2 |
18 files changed, 435 insertions, 126 deletions
diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index fea6e8d..15cc109 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -165,7 +165,7 @@ VisualID QEgl::getCompatibleVisualId(EGLConfig config) if (chosenVisualInfo) { // Skip size checks if implementation supports non-matching visual // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). - if (QEgl::hasExtension("EGL_NV_post_convert_replication")) + if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) return visualId; int visualRedSize = countBits(chosenVisualInfo->red_mask); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 97499f3..4ffd284 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2270,9 +2270,11 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) } else { d->selectionModel->setCurrentIndex(newCurrent, command); d->pressedPosition = visualRect(newCurrent).center() + d->offset(); - // We copy the same behaviour as for mousePressEvent(). - QRect rect(d->pressedPosition - d->offset(), QSize(1, 1)); - setSelection(rect, command); + if (newCurrent.isValid()) { + // We copy the same behaviour as for mousePressEvent(). + QRect rect(d->pressedPosition - d->offset(), QSize(1, 1)); + setSelection(rect, command); + } } event->accept(); return; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index e64ebb1..670bf34 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -135,6 +135,38 @@ void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, boo } #endif +void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) +{ + if (QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control)) { + QWidget *const widget = QWidgetPrivate::mapper->value(control); + QWidget *const window = widget->window(); + if (QTLWExtra *topData = qt_widget_private(window)->maybeTopData()) { + QWidgetBackingStoreTracker &backingStore = topData->backingStore; + if (visible) { + if (backingStore.data()) { + backingStore.registerWidget(widget); + } else { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdRestoreLayer); +#endif + backingStore.create(window); + backingStore.registerWidget(widget); + qt_widget_private(widget)->invalidateBuffer(widget->rect()); + widget->repaint(); + } + } else { +#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS + S60->wsSession().SendEffectCommand(ETfxCmdDeallocateLayer); +#endif + backingStore.unregisterWidget(widget); + // In order to ensure that any resources used by the window surface + // are immediately freed, we flush the WSERV command buffer. + S60->wsSession().Flush(); + } + } + } +} + bool qt_nograb() // application no-grab option { #if defined(QT_DEBUG) @@ -1475,6 +1507,8 @@ void qt_init(QApplicationPrivate * /* priv */, int) S60->avkonComponentsSupportTransparency = (value==1) ? true : false; } } + delete repository; + repository = 0; #endif #ifdef QT_KEYPAD_NAVIGATION @@ -1920,35 +1954,10 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent if (callSymbianEventFilters(symbianEvent)) return 1; const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged(); - QWidget *w = QWidgetPrivate::mapper->value(control); - QWidget *const window = w->window(); - if (!window->d_func()->maybeTopData()) - break; - QRefCountedWidgetBackingStore &backingStore = window->d_func()->maybeTopData()->backingStore; - if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS - S60->wsSession().SendEffectCommand(ETfxCmdDeallocateLayer); -#endif - // Decrement backing store reference count - backingStore.deref(); - // In order to ensure that any resources used by the window surface - // are immediately freed, we flush the WSERV command buffer. - S60->wsSession().Flush(); - } else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) { - if (backingStore.data()) { - // Increment backing store reference count - backingStore.ref(); - } else { -#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS - S60->wsSession().SendEffectCommand(ETfxCmdRestoreLayer); -#endif - // Create backing store with an initial reference count of 1 - backingStore.create(window); - backingStore.ref(); - w->d_func()->invalidateBuffer(w->rect()); - w->repaint(); - } - } + if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) + S60->controlVisibilityChanged(control, false); + else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) + S60->controlVisibilityChanged(control, true); return 1; } break; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index fe9dd8a..e768a21 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -129,7 +129,12 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) { QList<QGestureRecognizer *> list = m_recognizers.values(type); - m_recognizers.remove(type); + while (QGestureRecognizer *recognizer = m_recognizers.take(type)) { + if (!m_obsoleteGestures.contains(recognizer)) { + // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager + m_obsoleteGestures.insert(recognizer, QSet<QGesture *>()); + } + } foreach (QGesture *g, m_gestureToRecognizer.keys()) { QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); if (list.contains(recognizer)) { diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index a18ea07..ad6a99a 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -164,6 +164,7 @@ public: static inline CEikButtonGroupContainer* buttonGroupContainer(); static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); #endif + static void controlVisibilityChanged(CCoeControl *control, bool visible); #ifdef Q_OS_SYMBIAN TTrapHandler *s60InstalledTrapHandler; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index aaa29a1..dad4848 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -162,47 +162,76 @@ static inline bool hasBackingStoreSupport() extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp +/*! + \internal + \class QWidgetBackingStoreTracker + \brief Class which allows tracking of which widgets are using a given backing store -QRefCountedWidgetBackingStore::QRefCountedWidgetBackingStore() + QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer, + which maintains a list of the QWidgets which are currently using the backing + store. This list is modified via the registerWidget and unregisterWidget functions. + */ + +QWidgetBackingStoreTracker::QWidgetBackingStoreTracker() : m_ptr(0) - , m_count(0) { } -QRefCountedWidgetBackingStore::~QRefCountedWidgetBackingStore() +QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker() { delete m_ptr; } -void QRefCountedWidgetBackingStore::create(QWidget *widget) +/*! + \internal + Destroy the contained QWidgetBackingStore, if not null, and clear the list of + widgets using the backing store, then create a new QWidgetBackingStore, providing + the QWidget. + */ +void QWidgetBackingStoreTracker::create(QWidget *widget) { destroy(); m_ptr = new QWidgetBackingStore(widget); - m_count = 0; } -void QRefCountedWidgetBackingStore::destroy() +/*! + \internal + Destroy the contained QWidgetBackingStore, if not null, and clear the list of + widgets using the backing store. + */ +void QWidgetBackingStoreTracker::destroy() { delete m_ptr; m_ptr = 0; - m_count = 0; + m_widgets.clear(); } -void QRefCountedWidgetBackingStore::ref() +/*! + \internal + Add the widget to the list of widgets currently using the backing store. + If the widget was already in the list, this function is a no-op. + */ +void QWidgetBackingStoreTracker::registerWidget(QWidget *w) { Q_ASSERT(m_ptr); - ++m_count; + Q_ASSERT(w->internalWinId()); + Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr); + m_widgets.insert(w); } -void QRefCountedWidgetBackingStore::deref() +/*! + \internal + Remove the widget from the list of widgets currently using the backing store. + If the widget was in the list, and removing it causes the list to be empty, + the backing store is deleted. + If the widget was not in the list, this function is a no-op. + */ +void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w) { - if (m_count) { - Q_ASSERT(m_ptr); - if (0 == --m_count) { - delete m_ptr; - m_ptr = 0; - } + if (m_widgets.remove(w) && m_widgets.isEmpty()) { + delete m_ptr; + m_ptr = 0; } } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 8ae6a99..1979c84 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2796,10 +2796,14 @@ void QWidgetPrivate::setSubWindowStacking(bool set) if (QWidget *parent = q->parentWidget()) { if (parent->testAttribute(Qt::WA_WState_Created)) { - if (set) - [qt_mac_window_for(parent) addChildWindow:qt_mac_window_for(q) ordered:NSWindowAbove]; - else + if (set) { + if (parent->isVisible()) { + NSWindow *childwin = qt_mac_window_for(q); + [qt_mac_window_for(parent) addChildWindow:childwin ordered:NSWindowAbove]; + } + } else { [qt_mac_window_for(parent) removeChildWindow:qt_mac_window_for(q)]; + } } } @@ -2807,10 +2811,12 @@ void QWidgetPrivate::setSubWindowStacking(bool set) for (int i=0; i<widgets.size(); ++i) { QWidget *child = widgets.at(i); if (child->isWindow() && child->testAttribute(Qt::WA_WState_Created) && child->isVisibleTo(q)) { - if (set) - [qt_mac_window_for(q) addChildWindow:qt_mac_window_for(child) ordered:NSWindowAbove]; - else + if (set) { + NSWindow *childwin = qt_mac_window_for(child); + [qt_mac_window_for(q) addChildWindow:childwin ordered:NSWindowAbove]; + } else { [qt_mac_window_for(q) removeChildWindow:qt_mac_window_for(child)]; + } } } } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 587d7fb..4a79dc7 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -110,17 +110,18 @@ class QWidgetItemV2; class QStyle; -class Q_AUTOTEST_EXPORT QRefCountedWidgetBackingStore +class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker { + public: - QRefCountedWidgetBackingStore(); - ~QRefCountedWidgetBackingStore(); + QWidgetBackingStoreTracker(); + ~QWidgetBackingStoreTracker(); void create(QWidget *tlw); void destroy(); - void ref(); - void deref(); + void registerWidget(QWidget *w); + void unregisterWidget(QWidget *w); inline QWidgetBackingStore* data() { @@ -143,11 +144,11 @@ public: } private: - Q_DISABLE_COPY(QRefCountedWidgetBackingStore) + Q_DISABLE_COPY(QWidgetBackingStoreTracker) private: QWidgetBackingStore* m_ptr; - int m_count; + QSet<QWidget *> m_widgets; }; struct QTLWExtra { @@ -156,7 +157,7 @@ struct QTLWExtra { // Regular pointers (keep them together to avoid gaps on 64 bits architectures). QIcon *icon; // widget icon QPixmap *iconPixmap; - QRefCountedWidgetBackingStore backingStore; + QWidgetBackingStoreTracker backingStore; QWindowSurface *windowSurface; QPainter *sharedPainter; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 56349ad..319f330 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -684,6 +684,12 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) QSymbianControl *old_winid = static_cast<QSymbianControl *>(wasCreated ? data.winid : 0); if ((q->windowType() == Qt::Desktop)) old_winid = 0; + + // old_winid may not have received a 'not visible' visibility + // changed event before being destroyed; make sure that it is + // removed from the backing store's list of visible windows. + S60->controlVisibilityChanged(old_winid, false); + setWinId(0); // hide and reparent our own window away. Otherwise we might get diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index dfa4a48..793d380 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -212,6 +212,7 @@ if(mmx|3dnow|sse|sse2|iwmmxt) { SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp SSE_SOURCES += painting/qdrawhelper_sse.cpp SSE2_SOURCES += painting/qdrawhelper_sse2.cpp + SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp } diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 83751ed..ac9b994 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -352,7 +352,7 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowS // Always flush repainted areas. dirtyOnScreen += toClean; -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) && !defined(Q_BACKINGSTORE_SUBSURFACES) toClean.translate(tlwOffset); #endif @@ -1294,7 +1294,12 @@ void QWidgetBackingStore::sync() #ifdef Q_BACKINGSTORE_SUBSURFACES QWindowSurface *subSurface = w->windowSurface(); BeginPaintInfo beginPaintInfo; - beginPaint(toBePainted, w, subSurface, &beginPaintInfo, false); + + QPoint off = w->mapTo(tlw, QPoint()); + toBePainted.translate(off); + beginPaint(toBePainted, w, subSurface, &beginPaintInfo, true); + toBePainted.translate(-off); + if (beginPaintInfo.nothingToPaint) continue; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 1ff3d7b..276da93 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -7840,6 +7840,17 @@ void qInitDrawhelperAsm() qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; + +#if defined(QT_HAVE_SSSE3) + if (features & SSSE3) { + extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; + } +#endif // QT_HAVE_SSSE3 } else #endif { diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp new file mode 100644 index 0000000..9c02009 --- /dev/null +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifdef QT_HAVE_SSSE3 + +#include <private/qsimd_p.h> +#include <private/qdrawhelper_x86_p.h> +#include <private/qdrawingprimitive_sse2_p.h> + +QT_BEGIN_NAMESPACE + +inline static void blend_pixel(quint32 &dst, const quint32 src) +{ + if (src >= 0xff000000) + dst = src; + else if (src != 0) + dst = src + BYTE_MUL(dst, qAlpha(~src)); +} + + +/* The instruction palignr uses direct arguments, so we have to generate the code fo the different + shift (4, 8, 12). Checking the alignment inside the loop is unfortunatelly way too slow. + */ +#define BLENDING_LOOP(palignrOffset, length)\ + for (; x < length-3; x += 4) { \ + const __m128i srcVectorLastLoaded = _mm_load_si128((__m128i *)&src[x - minusOffsetToAlignSrcOn16Bytes + 4]);\ + const __m128i srcVector = _mm_alignr_epi8(srcVectorLastLoaded, srcVectorPrevLoaded, palignrOffset); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + _mm_store_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + __m128i alphaChannel = _mm_shuffle_epi8(srcVector, alphaShuffleMask); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_store_si128((__m128i *)&dst[x], result); \ + } \ + srcVectorPrevLoaded = srcVectorLastLoaded;\ + } + + +#define BLEND_SOURCE_OVER_ARGB32_FIRST_ROW_SSSE3(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ +\ + /* First, get dst aligned. */ \ + const int offsetToAlignOn16Bytes = (4 - ((reinterpret_cast<quintptr>(dst) >> 2) & 0x3)) & 0x3;\ + const int prologLength = qMin(length, offsetToAlignOn16Bytes);\ +\ + for (; x < prologLength; ++x) {\ + blend_pixel(dst[x], src[x]); \ + } \ +\ + const int minusOffsetToAlignSrcOn16Bytes = (reinterpret_cast<quintptr>(&(src[x])) >> 2) & 0x3;\ +\ + if (!minusOffsetToAlignSrcOn16Bytes) {\ + /* src is aligned, usual algorithm but with aligned operations.\ + See the SSE2 version for more documentation on the algorithm itself. */\ + const __m128i alphaShuffleMask = _mm_set_epi8(0xff,15,0xff,15,0xff,11,0xff,11,0xff,7,0xff,7,0xff,3,0xff,3);\ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_load_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + _mm_store_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + __m128i alphaChannel = _mm_shuffle_epi8(srcVector, alphaShuffleMask); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_store_si128((__m128i *)&dst[x], result); \ + } \ + } /* end for() */\ + } else if ((length - x) >= 8) {\ + /* We are at the first line, so "x - minusOffsetToAlignSrcOn16Bytes" could go before src, and\ + generate an invalid access. */\ +\ + /* We use two vectors to extract the src: prevLoaded for the first pixels, lastLoaded for the current pixels. */\ + __m128i srcVectorPrevLoaded;\ + if (minusOffsetToAlignSrcOn16Bytes > prologLength) {\ + /* We go forward 4 pixels to avoid reading before src. */\ + for (; x < prologLength + 4; ++x)\ + blend_pixel(dst[x], src[x]); \ + }\ + srcVectorPrevLoaded = _mm_load_si128((__m128i *)&src[x - minusOffsetToAlignSrcOn16Bytes]);\ + const int palignrOffset = minusOffsetToAlignSrcOn16Bytes << 2;\ +\ + const __m128i alphaShuffleMask = _mm_set_epi8(0xff,15,0xff,15,0xff,11,0xff,11,0xff,7,0xff,7,0xff,3,0xff,3);\ + switch (palignrOffset) {\ + case 4:\ + BLENDING_LOOP(4, length)\ + break;\ + case 8:\ + BLENDING_LOOP(8, length)\ + break;\ + case 12:\ + BLENDING_LOOP(12, length)\ + break;\ + }\ + }\ + for (; x < length; ++x) \ + blend_pixel(dst[x], src[x]); \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +//const __m128i alphaMask = _mm_set1_epi32(0xff000000); +// +// The computation being done is: +// result = s + d * (1-alpha) +// with shortcuts if fully opaque or fully transparent. +#define BLEND_SOURCE_OVER_ARGB32_MAIN_SSSE3(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ +\ + /* First, get dst aligned. */ \ + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) { \ + blend_pixel(dst[x], src[x]); \ + } \ +\ + const int minusOffsetToAlignSrcOn16Bytes = (reinterpret_cast<quintptr>(&(src[x])) >> 2) & 0x3;\ +\ + if (!minusOffsetToAlignSrcOn16Bytes) {\ + /* src is aligned, usual algorithm but with aligned operations.\ + See the SSE2 version for more documentation on the algorithm itself. */\ + const __m128i alphaShuffleMask = _mm_set_epi8(0xff,15,0xff,15,0xff,11,0xff,11,0xff,7,0xff,7,0xff,3,0xff,3);\ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_load_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + _mm_store_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + __m128i alphaChannel = _mm_shuffle_epi8(srcVector, alphaShuffleMask); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + const __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_store_si128((__m128i *)&dst[x], result); \ + } \ + } /* end for() */\ + } else if ((length - x) >= 8) {\ + /* We use two vectors to extract the src: prevLoaded for the first pixels, lastLoaded for the current pixels. */\ + __m128i srcVectorPrevLoaded = _mm_load_si128((__m128i *)&src[x - minusOffsetToAlignSrcOn16Bytes]);\ + const int palignrOffset = minusOffsetToAlignSrcOn16Bytes << 2;\ +\ + const __m128i alphaShuffleMask = _mm_set_epi8(0xff,15,0xff,15,0xff,11,0xff,11,0xff,7,0xff,7,0xff,3,0xff,3);\ + switch (palignrOffset) {\ + case 4:\ + BLENDING_LOOP(4, length)\ + break;\ + case 8:\ + BLENDING_LOOP(8, length)\ + break;\ + case 12:\ + BLENDING_LOOP(12, length)\ + break;\ + }\ + }\ + for (; x < length; ++x) \ + blend_pixel(dst[x], src[x]); \ +} + +void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (quint32 *) destPixels; + if (const_alpha == 256) { + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + const __m128i nullVector = _mm_setzero_si128(); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i one = _mm_set1_epi16(0xff); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + // We have to unrol the first row in order to deal with the load on unaligned data + // prior to the src pointer. + BLEND_SOURCE_OVER_ARGB32_FIRST_ROW_SSSE3(dst, src, w, nullVector, half, one, colorMask, alphaMask); + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + + for (int y = 1; y < h; ++y) { + BLEND_SOURCE_OVER_ARGB32_MAIN_SSSE3(dst, src, w, nullVector, half, one, colorMask, alphaMask); + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } else if (const_alpha != 0) { + // dest = (s + d * sia) * ca + d * cia + // = s * ca + d * (sia * ca + cia) + // = s * ca + d * (1 - sa*ca) + const_alpha = (const_alpha * 255) >> 8; + const __m128i nullVector = _mm_setzero_si128(); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i one = _mm_set1_epi16(0xff); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + for (int y = 0; y < h; ++y) { + BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, w, nullVector, half, one, colorMask, constAlphaVector) + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_SSSE3 diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c index 5e7c67a..94039fb 100644 --- a/src/gui/painting/qgrayraster.c +++ b/src/gui/painting/qgrayraster.c @@ -956,53 +956,49 @@ const QT_FT_Vector* control2, const QT_FT_Vector* to ) { - TPos dx, dy, da, db; int top, level; int* levels; QT_FT_Vector* arc; + int mid_x = ( DOWNSCALE( ras.x ) + to->x + + 3 * (control1->x + control2->x ) ) / 8; + int mid_y = ( DOWNSCALE( ras.y ) + to->y + + 3 * (control1->y + control2->y ) ) / 8; + TPos dx = DOWNSCALE( ras.x ) + to->x - ( mid_x << 1 ); + TPos dy = DOWNSCALE( ras.y ) + to->y - ( mid_y << 1 ); - dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); if ( dx < 0 ) dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); if ( dy < 0 ) dy = -dy; if ( dx < dy ) dx = dy; - da = dx; - - dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - db = dx; level = 1; - da = da / ras.cubic_level; - db = db / ras.conic_level; - while ( da > 0 || db > 0 ) + dx /= ras.cubic_level; + while ( dx > 0 ) { - da >>= 2; - db >>= 3; + dx >>= 2; level++; } if ( level <= 1 ) { - TPos to_x, to_y, mid_x, mid_y; + TPos to_x, to_y; to_x = UPSCALE( to->x ); to_y = UPSCALE( to->y ); + + /* Recalculation of midpoint is needed only if */ + /* UPSCALE and DOWNSCALE have any effect. */ + +#if ( PIXEL_BITS != 6 ) mid_x = ( ras.x + to_x + 3 * UPSCALE( control1->x + control2->x ) ) / 8; mid_y = ( ras.y + to_y + 3 * UPSCALE( control1->y + control2->y ) ) / 8; +#endif gray_render_line( RAS_VAR_ mid_x, mid_y ); gray_render_line( RAS_VAR_ to_x, to_y ); @@ -1359,10 +1355,6 @@ /* <Input> */ /* outline :: A pointer to the source target. */ /* */ - /* func_interface :: A table of `emitters', i.e,. function pointers */ - /* called during decomposition to indicate path */ - /* operations. */ - /* */ /* user :: A typeless pointer which is passed to each */ /* emitter during the decomposition. It can be */ /* used to store the state during the */ @@ -1373,15 +1365,10 @@ /* */ static int QT_FT_Outline_Decompose( const QT_FT_Outline* outline, - const QT_FT_Outline_Funcs* func_interface, void* user ) { #undef SCALED -#if 0 -#define SCALED( x ) ( ( (x) << shift ) - delta ) -#else #define SCALED( x ) (x) -#endif QT_FT_Vector v_last; QT_FT_Vector v_control; @@ -1396,12 +1383,6 @@ int error; char tag; /* current point's state */ -#if 0 - int shift = func_interface->shift; - TPos delta = func_interface->delta; -#endif - - first = 0; for ( n = 0; n < outline->n_contours; n++ ) @@ -1455,7 +1436,7 @@ tags--; } - error = func_interface->move_to( &v_start, user ); + error = gray_move_to( &v_start, user ); if ( error ) goto Exit; @@ -1475,7 +1456,7 @@ vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); - error = func_interface->line_to( &vec, user ); + error = gray_line_to( &vec, user ); if ( error ) goto Exit; continue; @@ -1502,7 +1483,7 @@ if ( tag == QT_FT_CURVE_TAG_ON ) { - error = func_interface->conic_to( &v_control, &vec, + error = gray_conic_to( &v_control, &vec, user ); if ( error ) goto Exit; @@ -1515,7 +1496,7 @@ v_middle.x = ( v_control.x + vec.x ) / 2; v_middle.y = ( v_control.y + vec.y ) / 2; - error = func_interface->conic_to( &v_control, &v_middle, + error = gray_conic_to( &v_control, &v_middle, user ); if ( error ) goto Exit; @@ -1524,7 +1505,7 @@ goto Do_Conic; } - error = func_interface->conic_to( &v_control, &v_start, + error = gray_conic_to( &v_control, &v_start, user ); goto Close; } @@ -1555,20 +1536,20 @@ vec.x = SCALED( point->x ); vec.y = SCALED( point->y ); - error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); + error = gray_cubic_to( &vec1, &vec2, &vec, user ); if ( error ) goto Exit; continue; } - error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); + error = gray_cubic_to( &vec1, &vec2, &v_start, user ); goto Close; } } } /* close the contour with a line segment */ - error = func_interface->line_to( &v_start, user ); + error = gray_line_to( &v_start, user ); Close: if ( error ) @@ -1596,22 +1577,11 @@ static int gray_convert_glyph_inner( RAS_ARG ) { - static - const QT_FT_Outline_Funcs func_interface = - { - (QT_FT_Outline_MoveTo_Func) gray_move_to, - (QT_FT_Outline_LineTo_Func) gray_line_to, - (QT_FT_Outline_ConicTo_Func)gray_conic_to, - (QT_FT_Outline_CubicTo_Func)gray_cubic_to, - 0, - 0 - }; - volatile int error = 0; if ( qt_ft_setjmp( ras.jump_buffer ) == 0 ) { - error = QT_FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); + error = QT_FT_Outline_Decompose( &ras.outline, &ras ); gray_record_cell( RAS_VAR ); } else diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index e521e01..5307142 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -1516,8 +1516,8 @@ void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints for (int i = 0; i < pointCount; ++i) { translated_points[i] = polygonPoints[i] + offset; - translated_points[i].rx() = qRound(translated_points[i].x()) + offs; - translated_points[i].ry() = qRound(translated_points[i].y()) + offs; + translated_points[i].rx() = qFloor(translated_points[i].x()) + offs; + translated_points[i].ry() = qFloor(translated_points[i].y()) + offs; } fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode); @@ -1754,8 +1754,8 @@ void QX11PaintEnginePrivate::fillPath(const QPainterPath &path, QX11PaintEngineP for (int j = 0; j < polys.at(i).size(); ++j) { translated_points[j] = polys.at(i).at(j); if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) { - translated_points[j].rx() = qRound(translated_points[j].rx() + aliasedCoordinateDelta) + offs; - translated_points[j].ry() = qRound(translated_points[j].ry() + aliasedCoordinateDelta) + offs; + translated_points[j].rx() = qFloor(translated_points[j].rx() + aliasedCoordinateDelta) + offs; + translated_points[j].ry() = qFloor(translated_points[j].ry() + aliasedCoordinateDelta) + offs; } } diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp index a816ed2..170668b 100644 --- a/src/gui/painting/qwindowsurface_qws.cpp +++ b/src/gui/painting/qwindowsurface_qws.cpp @@ -882,7 +882,11 @@ void QWSMemorySurface::beginPaint(const QRegion &rgn) const QVector<QRect> rects = rgn.rects(); const QColor blank = Qt::transparent; for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { - p.fillRect(*it, blank); + QRect r = *it; +#ifdef Q_BACKINGSTORE_SUBSURFACES + r.translate(painterOffset()); +#endif + p.fillRect(r, blank); } } QWSWindowSurface::beginPaint(rgn); diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 5fb3384..d25fb05 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1156,6 +1156,10 @@ Qt::LayoutDirection QTextBlock::textDirection() const if (dir != Qt::LayoutDirectionAuto) return dir; + dir = p->defaultTextOption.textDirection(); + if (dir != Qt::LayoutDirectionAuto) + return dir; + const QString buffer = p->buffer(); const int pos = position(); diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index 04d6de9..e718212 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -921,10 +921,12 @@ void QCompleterPrivate::showPopup(const QRect& rect) void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path) { Q_Q(QCompleter); +#ifndef QT_NO_LINEEDIT QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget); //the path given by QFileSystemModel does not end with / if (lineEdit && !lineEdit->text().isEmpty() && !q->completionPrefix().isEmpty() && q->completionPrefix() != path + QLatin1Char('/')) q->complete(); +#endif } /*! |