diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/effects/qgraphicseffect.cpp | 14 | ||||
-rw-r--r-- | src/gui/egl/qegl.cpp | 64 | ||||
-rw-r--r-- | src/gui/egl/qegl_p.h | 12 | ||||
-rw-r--r-- | src/gui/egl/qegl_qws.cpp | 6 | ||||
-rw-r--r-- | src/gui/egl/qegl_symbian.cpp | 8 | ||||
-rw-r--r-- | src/gui/egl/qegl_wince.cpp | 13 | ||||
-rw-r--r-- | src/gui/egl/qegl_x11.cpp | 7 | ||||
-rw-r--r-- | src/gui/egl/qeglproperties.cpp | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 30 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 33 | ||||
-rw-r--r-- | src/gui/image/qimagepixmapcleanuphooks.cpp | 21 | ||||
-rw-r--r-- | src/gui/image/qimagepixmapcleanuphooks_p.h | 3 | ||||
-rw-r--r-- | src/gui/image/qpixmap.cpp | 9 | ||||
-rw-r--r-- | src/gui/kernel/qeventdispatcher_mac.mm | 8 | ||||
-rw-r--r-- | src/gui/painting/qcups.cpp | 4 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 49 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_sse2.cpp | 211 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_x86_p.h | 8 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 7 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase_win.cpp | 14 |
20 files changed, 409 insertions, 118 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 10ef5ea..7d1d03d 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -699,12 +699,17 @@ void QGraphicsColorizeEffect::draw(QPainter *painter) if (sourceIsPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, NoPad); - d->filter->draw(painter, offset, pixmap); + if (!pixmap.isNull()) + d->filter->draw(painter, offset, pixmap); + return; } // Draw pixmap in deviceCoordinates to avoid pixmap scaling. const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset); + if (pixmap.isNull()) + return; + QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -858,9 +863,11 @@ void QGraphicsBlurEffect::draw(QPainter *painter) if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) mode = NoPad; - // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode); + if (pixmap.isNull()) + return; + d->filter->draw(painter, offset, pixmap); } @@ -1047,6 +1054,9 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter) // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode); + if (pixmap.isNull()) + return; + QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index ae3d6c3..4d447cb 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -54,9 +54,10 @@ QT_BEGIN_NAMESPACE static QEglContext * volatile currentGLContext = 0; static QEglContext * volatile currentVGContext = 0; +EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY; + QEglContext::QEglContext() : apiType(QEgl::OpenGL) - , dpy(EGL_NO_DISPLAY) , ctx(EGL_NO_CONTEXT) , cfg(0) , currentSurface(EGL_NO_SURFACE) @@ -68,7 +69,7 @@ QEglContext::QEglContext() QEglContext::~QEglContext() { - destroy(); + destroyContext(); if (currentGLContext == this) currentGLContext = 0; @@ -86,14 +87,6 @@ bool QEglContext::isCurrent() const return current; } -// Open the EGL display associated with "device". -bool QEglContext::openDisplay(QPaintDevice *device) -{ - if (dpy == EGL_NO_DISPLAY) - dpy = defaultDisplay(device); - return (dpy != EGL_NO_DISPLAY); -} - // Choose a configuration that matches "properties". bool QEglContext::chooseConfig (const QEglProperties& properties, QEgl::PixelFormatMatch match) @@ -102,7 +95,7 @@ bool QEglContext::chooseConfig do { // Get the number of matching configurations for this set of properties. EGLint matching = 0; - if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching) + if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching) continue; // If we want the best pixel format, then return the first @@ -179,7 +172,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) shareContext = 0; if (shareContext) { - ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties()); + ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties()); if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); shareContext = 0; @@ -209,7 +202,7 @@ void QEglContext::destroySurface(EGLSurface surface) } // Destroy the context. Note: this does not destroy the surface. -void QEglContext::destroy() +void QEglContext::destroyContext() { if (ctx != EGL_NO_CONTEXT && ownsContext) eglDestroyContext(dpy, ctx); @@ -248,7 +241,7 @@ bool QEglContext::makeCurrent(EGLSurface surface) eglBindAPI(EGL_OPENVG_API); #endif - bool ok = eglMakeCurrent(dpy, surface, surface, ctx); + bool ok = eglMakeCurrent(display(), surface, surface, ctx); if (!ok) qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError()); return ok; @@ -277,7 +270,7 @@ bool QEglContext::doneCurrent() eglBindAPI(EGL_OPENVG_API); #endif - bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + bool ok = eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError()); return ok; @@ -299,7 +292,7 @@ bool QEglContext::swapBuffers(EGLSurface surface) if(ctx == EGL_NO_CONTEXT) return false; - bool ok = eglSwapBuffers(dpy, surface); + bool ok = eglSwapBuffers(display(), surface); if (!ok) qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); return ok; @@ -338,7 +331,7 @@ void QEglContext::waitClient() // Query the value of a configuration attribute. bool QEglContext::configAttrib(int name, EGLint *value) const { - return eglGetConfigAttrib(dpy, cfg, name, value); + return eglGetConfigAttrib(display(), cfg, name, value); } // Retrieve all of the properties on "cfg". If zero, return @@ -357,27 +350,38 @@ QEglProperties QEglContext::configProperties(EGLConfig cfg) const return props; } -// Initialize and return the default display. -EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device) +EGLDisplay QEglContext::display() { - static EGLDisplay dpy = EGL_NO_DISPLAY; - if (dpy == EGL_NO_DISPLAY) { - dpy = getDisplay(device); + static bool openedDisplay = false; + + if (!openedDisplay) { + dpy = eglGetDisplay(nativeDisplay()); + openedDisplay = true; + if (dpy == EGL_NO_DISPLAY) { + qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); + dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); + } if (dpy == EGL_NO_DISPLAY) { - qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display"; + qWarning("QEglContext::display(): Can't even open the default display"); return EGL_NO_DISPLAY; } + if (!eglInitialize(dpy, NULL, NULL)) { - qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError()); + qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError()); return EGL_NO_DISPLAY; } -#ifdef EGL_OPENGL_ES_API - eglBindAPI(EGL_OPENGL_ES_API); -#endif } + return dpy; } +#if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly +EGLNativeDisplayType QEglContext::nativeDisplay() +{ + return EGL_DEFAULT_DISPLAY; +} +#endif + // Return the error string associated with a specific code. QString QEglContext::errorString(EGLint code) { @@ -410,7 +414,7 @@ void QEglContext::dumpAllConfigs() { QEglProperties props; EGLint count = 0; - if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1) + if (!eglGetConfigs(display(), 0, 0, &count) || count < 1) return; EGLConfig *configs = new EGLConfig [count]; eglGetConfigs(dpy, configs, count, &count); @@ -423,7 +427,7 @@ void QEglContext::dumpAllConfigs() QString QEglContext::extensions() { - const char* exts = eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS); + const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS); return QString(QLatin1String(exts)); } @@ -431,7 +435,7 @@ bool QEglContext::hasExtension(const char* extensionName) { QList<QByteArray> extensions = QByteArray(reinterpret_cast<const char *> - (eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS))).split(' '); + (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' '); return extensions.contains(extensionName); } diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index a7de9c8..87ed818 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -86,14 +86,12 @@ public: QEgl::API api() const { return apiType; } void setApi(QEgl::API api) { apiType = api; } - bool openDisplay(QPaintDevice *device); bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0); + void destroyContext(); EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0); void destroySurface(EGLSurface surface); - void destroy(); - bool makeCurrent(EGLSurface surface); bool doneCurrent(); bool lazyDoneCurrent(); @@ -108,7 +106,7 @@ public: static EGLint error() { return eglGetError(); } static QString errorString(EGLint code); - EGLDisplay display() const { return dpy; } + static EGLDisplay display(); EGLContext context() const { return ctx; } void setContext(EGLContext context) { ctx = context; ownsContext = false;} @@ -118,8 +116,6 @@ public: QEglProperties configProperties(EGLConfig cfg = 0) const; - static EGLDisplay defaultDisplay(QPaintDevice *device); - void dumpAllConfigs(); static QString extensions(); @@ -127,7 +123,6 @@ public: private: QEgl::API apiType; - EGLDisplay dpy; EGLContext ctx; EGLConfig cfg; EGLSurface currentSurface; @@ -135,7 +130,8 @@ private: bool ownsContext; bool sharing; - static EGLDisplay getDisplay(QPaintDevice *device); + static EGLDisplay dpy; + static EGLNativeDisplayType nativeDisplay(); static QEglContext *currentContext(QEgl::API api); static void setCurrentContext(QEgl::API api, QEglContext *context); diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp index e999e0b..2a61beb 100644 --- a/src/gui/egl/qegl_qws.cpp +++ b/src/gui/egl/qegl_qws.cpp @@ -64,12 +64,6 @@ EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties return EGL_NO_SURFACE; } -EGLDisplay QEglContext::getDisplay(QPaintDevice *device) -{ - Q_UNUSED(device); - return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); -} - static QScreen *screenForDevice(QPaintDevice *device) { QScreen *screen = qt_screen; diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp index 44ecd19..b1c9408 100644 --- a/src/gui/egl/qegl_symbian.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -86,14 +86,6 @@ EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties return surf; } -EGLDisplay QEglContext::getDisplay(QPaintDevice *device) -{ - EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (dpy == EGL_NO_DISPLAY) - qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY"); - return dpy; -} - // Set pixel format and other properties based on a paint device. void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) { diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp index 026a7b1..c9c9773 100644 --- a/src/gui/egl/qegl_wince.cpp +++ b/src/gui/egl/qegl_wince.cpp @@ -87,20 +87,15 @@ EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties return surf; } -EGLDisplay QEglContext::getDisplay(QPaintDevice *device) +EGLNativeDisplayType QEglContext::nativeDisplay() { - EGLDisplay dpy = 0; HWND win = (static_cast<QWidget*>(device))->winId(); HDC myDc = GetDC(win); if (!myDc) { - qWarning("QEglContext::defaultDisplay(): WinCE display is not open"); + qWarning("QEglContext::nativeDisplay(): WinCE display is not open"); + return EGL_DEFAULT_DISPLAY; } - dpy = eglGetDisplay(EGLNativeDisplayType(myDc)); - if (dpy == EGL_NO_DISPLAY) { - qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY"); - dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - } - return dpy; + return EGLNativeDisplayType(myDc); } // Set pixel format and other properties based on a paint device. diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 2cf4e33..634ff13 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -93,15 +93,14 @@ EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties return surf; } -EGLDisplay QEglContext::getDisplay(QPaintDevice *device) +EGLNativeDisplayType QEglContext::nativeDisplay() { - Q_UNUSED(device); Display *xdpy = QX11Info::display(); if (!xdpy) { qWarning("QEglContext::getDisplay(): X11 display is not open"); - return EGL_NO_DISPLAY; + return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); } - return eglGetDisplay(EGLNativeDisplayType(xdpy)); + return EGLNativeDisplayType(xdpy); } static int countBits(unsigned long mask) diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index 2915fb9..236ec37 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -60,7 +60,7 @@ QEglProperties::QEglProperties(EGLConfig cfg) props.append(EGL_NONE); for (int name = 0x3020; name <= 0x304F; ++name) { EGLint value; - if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::defaultDisplay(0), cfg, name, &value)) + if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::display(), cfg, name, &value)) setValue(name, value); } eglGetError(); // Clear the error state. @@ -273,12 +273,12 @@ static void addTag(QString& str, const QString& tag) void QEglProperties::dumpAllConfigs() { EGLint count = 0; - eglGetConfigs(QEglContext::defaultDisplay(0), 0, 0, &count); + eglGetConfigs(QEglContext::display(), 0, 0, &count); if (count < 1) return; EGLConfig *configs = new EGLConfig [count]; - eglGetConfigs(QEglContext::defaultDisplay(0), configs, count, &count); + eglGetConfigs(QEglContext::display(), configs, count, &count); for (EGLint index = 0; index < count; ++index) qWarning() << QEglProperties(configs[index]).toString(); delete [] configs; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3cdf8ce..2f208b7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -357,19 +357,22 @@ default, child items are stacked on top of the parent item. But setting this flag, the child will be stacked behind it. This flag is useful for drop shadow effects and for decoration objects that follow the parent - item's geometry without drawing on top of it. + item's geometry without drawing on top of it. This flag was introduced + in Qt 4.5. \value ItemUsesExtendedStyleOption The item makes use of either - \l{QStyleOptionGraphicsItem::}{exposedRect} or - \l{QStyleOptionGraphicsItem::}{matrix} in QStyleOptionGraphicsItem. By default, - the \l{QStyleOptionGraphicsItem::}{exposedRect} is initialized to the item's - boundingRect() and the \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. - You can enable this flag for the style options to be set up with more - fine-grained values. - Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag + \l{QStyleOptionGraphicsItem::} {exposedRect} or + \l{QStyleOptionGraphicsItem::} {matrix} in + QStyleOptionGraphicsItem. By default, the + \l{QStyleOptionGraphicsItem::} {exposedRect} is initialized to the + item's boundingRect() and the + \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. You can + enable this flag for the style options to be set up with more + fine-grained values. Note that + QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag and always initialized to 1. Use - QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need a higher - value. + QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need + a higher value. This flag was introduced in Qt 4.6. \value ItemHasNoContents The item does not paint anything (i.e., calling paint() on the item has no effect). You should set this flag on items that @@ -387,9 +390,10 @@ used for Asian languages. This flag was introduced in Qt 4.6. - \value ItemNegativeZStacksBehindParent The item automatically stacks behind - it's parent if it's z-value is negative. This flag enables setZValue() to - toggle ItemStacksBehindParent. + \value ItemNegativeZStacksBehindParent The item automatically + stacks behind it's parent if it's z-value is negative. This flag + enables setZValue() to toggle ItemStacksBehindParent. This flag + was introduced in Qt 4.6. \value ItemIsPanel The item is a panel. A panel provides activation and contained focus handling. Only one panel can be active at a time (see diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 66707fc..4472272 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5132,6 +5132,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } /*! + \obsolete + Paints the given \a items using the provided \a painter, after the background has been drawn, and before the foreground has been drawn. All painting is done in \e scene coordinates. Before @@ -5154,7 +5156,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0 - \obsolete Since Qt 4.6, this function is not called anymore unless + Since Qt 4.6, this function is not called anymore unless the QGraphicsView::IndirectPainting flag is given as an Optimization flag. @@ -5710,8 +5712,15 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent) item->d_ptr->acceptedTouchBeginEvent = true; bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted(); - if (!res) + if (!res) { + // forget about these touch points, we didn't handle them + for (int i = 0; i < touchEvent.touchPoints().count(); ++i) { + const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i); + itemForTouchPointId.remove(touchPoint.id()); + sceneCurrentTouchPoints.remove(touchPoint.id()); + } ignoreSceneTouchEvent = false; + } break; } default: @@ -5902,13 +5911,21 @@ void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures, QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); QList<QGraphicsObject *> result; for (int j = 0; j < items.size(); ++j) { - QGraphicsObject *item = items.at(j)->toGraphicsObject(); - if (!item) - continue; - QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); - if (d->gestureContext.contains(gestureType)) { - result.append(item); + QGraphicsItem *item = items.at(j); + + // Check if the item is blocked by a modal panel and use it as + // a target instead of this item. + (void) item->isBlockedByModalPanel(&item); + + if (QGraphicsObject *itemobj = item->toGraphicsObject()) { + QGraphicsItemPrivate *d = item->d_func(); + if (d->gestureContext.contains(gestureType)) { + result.append(itemobj); + } } + // Don't propagate through panels. + if (item->isPanel()) + break; } DEBUG() << "QGraphicsScenePrivate::getGestureTargets:" << gesture << result; diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp index ace4bb6..517fcb0 100644 --- a/src/gui/image/qimagepixmapcleanuphooks.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -122,19 +122,32 @@ void QImagePixmapCleanupHooks::executeImageHooks(qint64 key) qt_image_cleanup_hook_64(key); } -void QImagePixmapCleanupHooks::enableCleanupHooks(const QPixmap &pixmap) -{ - enableCleanupHooks(const_cast<QPixmap &>(pixmap).data_ptr().data()); -} void QImagePixmapCleanupHooks::enableCleanupHooks(QPixmapData *pixmapData) { pixmapData->is_cached = true; } +void QImagePixmapCleanupHooks::enableCleanupHooks(const QPixmap &pixmap) +{ + enableCleanupHooks(const_cast<QPixmap &>(pixmap).data_ptr().data()); +} + void QImagePixmapCleanupHooks::enableCleanupHooks(const QImage &image) { const_cast<QImage &>(image).data_ptr()->is_cached = true; } +bool QImagePixmapCleanupHooks::isImageCached(const QImage &image) +{ + return const_cast<QImage &>(image).data_ptr()->is_cached; +} + +bool QImagePixmapCleanupHooks::isPixmapCached(const QPixmap &pixmap) +{ + return const_cast<QPixmap&>(pixmap).data_ptr().data()->is_cached; +} + + + QT_END_NAMESPACE diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h index 88dd3a6..eae11f4 100644 --- a/src/gui/image/qimagepixmapcleanuphooks_p.h +++ b/src/gui/image/qimagepixmapcleanuphooks_p.h @@ -72,6 +72,9 @@ public: static void enableCleanupHooks(const QPixmap &pixmap); static void enableCleanupHooks(QPixmapData *pixmapData); + static bool isImageCached(const QImage &image); + static bool isPixmapCached(const QPixmap &pixmap); + // Gets called when a pixmap data is about to be modified: void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd); diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index d1e5c40..1df7946 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1670,10 +1670,9 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) \o The hasAlphaChannel() returns true if the pixmap has a format that - respects the alpha channel, otherwise returns false, while the - hasAlpha() function returns true if the pixmap has an alpha - channel \e or a mask (otherwise false). The mask() function returns - the mask as a QBitmap object, which can be set using setMask(). + respects the alpha channel, otherwise returns false. The hasAlpha(), + setMask() and mask() functions are legacy and should not be used. + They are potentially very slow. The createHeuristicMask() function creates and returns a 1-bpp heuristic mask (i.e. a QBitmap) for this pixmap. It works by @@ -1760,6 +1759,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) Returns true if this pixmap has an alpha channel, \e or has a mask, otherwise returns false. + \warning This is potentially an expensive operation. + \sa hasAlphaChannel(), mask() */ bool QPixmap::hasAlpha() const diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c7c7caf..df09185 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -492,6 +492,14 @@ static bool IsMouseOrKeyEvent( NSEvent* event ) case NSOtherMouseDown: case NSOtherMouseUp: case NSOtherMouseDragged: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + case NSEventTypeGesture: // touch events + case NSEventTypeMagnify: + case NSEventTypeSwipe: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: +#endif result = true; break; diff --git a/src/gui/painting/qcups.cpp b/src/gui/painting/qcups.cpp index 7903762..ac41692 100644 --- a/src/gui/painting/qcups.cpp +++ b/src/gui/painting/qcups.cpp @@ -342,7 +342,9 @@ bool QCUPSSupport::printerHasPPD(const char *printerName) { if (!isAvailable()) return false; - return _cupsGetPPD(printerName) != 0; + const char *ppdFile = _cupsGetPPD(printerName); + unlink(ppdFile); + return (ppdFile != 0); } QString QCUPSSupport::unicodeString(const char *s) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 7a3da20..070491d 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -8092,20 +8092,43 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse3dnow; } #endif // 3DNOW - extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha); - extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha); - qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; - qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; - qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; - qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; - } + +#ifdef QT_HAVE_SSE2 + if (features & SSE2) { + extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; + 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; + } else +#endif + { + extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; + } +} #endif // SSE #ifdef QT_HAVE_IWMMXT diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index dd6fa1b..6ac64d3 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -57,6 +57,217 @@ QT_BEGIN_NAMESPACE +/* + * Multiply the components of pixelVector by alphaChannel + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ +{ \ + /* 1. separate the colors in 2 vectors so each color is on 16 bits \ + (in order to be multiplied by the alpha \ + each 32 bit of dstVectorAG are in the form 0x00AA00GG \ + each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ + __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ + __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ + \ + /* 2. multiply the vectors by the alpha channel */\ + pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ + pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ + \ + /* 3. devide by 255, that's the tricky part. \ + we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ + /** so first (X + X/256 + rounding) */\ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ + \ + /** second devide by 256 */\ + pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ + /** for AG, we could >> 8 to divide followed by << 8 to put the \ + bytes in the correct position. By masking instead, we execute \ + only one instruction */\ + pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ + \ + /* 4. combine the 2 pairs of colors */ \ + result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ +} + +/* + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ + /* interpolate AG */\ + __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ + __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ + __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ + __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ + __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ + finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ + finalAG = _mm_add_epi16(finalAG, half); \ + finalAG = _mm_andnot_si128(colorMask, finalAG); \ + \ + /* interpolate RB */\ + __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ + __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ + __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ + __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ + __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ + finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ + finalRB = _mm_add_epi16(finalRB, half); \ + finalRB = _mm_srli_epi16(finalRB, 8); \ + \ + /* combine */\ + result = _mm_or_si128(finalAG, finalRB); \ +} + +void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (uint *) destPixels; + if (const_alpha == 256) { + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + 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); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { + // all opaque + _mm_storeu_si128((__m128i *)&dst[x], srcVector); + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { + // not fully transparent + // result = s + d * (1-alpha) + + // extract the alpha channel on 2 x 16 bits + // so we have room for the multiplication + // each 32 bits will be in the form 0x00AA00AA + // with A being the 1 - alpha + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + alphaChannel = _mm_sub_epi16(one, alphaChannel); + + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i destMultipliedByOneMinusAlpha; + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); + + // result = s + d * (1-alpha) + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + uint s = src[x]; + if (s >= 0xff000000) + dst[x] = s; + else if (s != 0) + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + 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_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 constAlphaVector = _mm_set1_epi16(const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); + + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + alphaChannel = _mm_sub_epi16(one, alphaChannel); + + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i destMultipliedByOneMinusAlpha; + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); + + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + quint32 s = src[x]; + if (s != 0) { + s = BYTE_MUL(s, const_alpha); + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } +} + +// qblendfunctions.cpp +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (uint *) destPixels; + if (const_alpha != 256) { + if (const_alpha != 0) { + const __m128i nullVector = _mm_set1_epi32(0); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + const_alpha = (const_alpha * 255) >> 8; + int one_minus_const_alpha = 255 - const_alpha; + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + const __m128i oneMinusConstAlpha = _mm_set1_epi16(one_minus_const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i result; + INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + quint32 s = src[x]; + s = BYTE_MUL(s, const_alpha); + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } + } else { + qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); + } +} + void qt_memfill32_sse2(quint32 *dest, quint32 value, int count) { if (count < 7) { diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 30aadd0..d7282a7 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -114,6 +114,14 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); +void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); #endif // QT_HAVE_SSE2 #ifdef QT_HAVE_IWMMXT diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 3bcaf8c..075c457 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -708,13 +708,14 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s) bool penTextureAlpha = false; if (penBrush.style() == Qt::TexturePattern) penTextureAlpha = qHasPixmapTexture(penBrush) - ? penBrush.texture().hasAlpha() + ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha() : penBrush.textureImage().hasAlphaChannel(); bool brushTextureAlpha = false; - if (s->brush.style() == Qt::TexturePattern) + if (s->brush.style() == Qt::TexturePattern) { brushTextureAlpha = qHasPixmapTexture(s->brush) - ? s->brush.texture().hasAlpha() + ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha() : s->brush.textureImage().hasAlphaChannel(); + } if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha) || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha)) && !engine->hasFeature(QPaintEngine::MaskedBrush)) diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index 05c8f08..a6ceee1 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -336,8 +336,18 @@ void addFontToDatabase(QString familyName, const QString &scriptName, signature->fsCsb[0], signature->fsCsb[1] }; QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); - for (int i = 0; i < systems.count(); ++i) - family->writingSystems[systems.at(i)] = QtFontFamily::Supported; + + for (int i = 0; i < systems.count(); ++i) { + QFontDatabase::WritingSystem writingSystem = systems.at(i); + + // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains + // the symbol for Baht, and Windows thus reports that it supports the Thai script. + // Since it's the default UI font on this platform, most widgets will be unable to + // display Thai text by default. As a temporary work around, we special case Segoe UI + // and remove the Thai script from its list of supported writing systems. + if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI")) + family->writingSystems[writingSystem] = QtFontFamily::Supported; + } } else if (!family->writingSystemCheck) { //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1()); if (scriptName == QLatin1String("Western") |