From 4248244704211a45a20a39f390ec00c9687a8d1c Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 21 Jan 2010 07:57:25 +0100 Subject: Fix how we select antialiasing method for text under Mac OS X Reviewed-by: Eskil --- src/gui/kernel/qapplication_mac.mm | 42 ++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 688e51f..7cdd50a 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -227,8 +227,29 @@ void onApplicationChangedActivation( bool activated ); static void qt_mac_read_fontsmoothing_settings() { - NSInteger appleFontSmoothing = [[NSUserDefaults standardUserDefaults] integerForKey:@"AppleFontSmoothing"]; - qt_applefontsmoothing_enabled = (appleFontSmoothing > 0); + qt_applefontsmoothing_enabled = true; + int w = 10, h = 10; + QImage image(w, h, QImage::Format_RGB32); + image.fill(0xffffffff); + QPainter p(&image); + p.drawText(0, h, "X\\"); + p.end(); + + const int *bits = (const int *) ((const QImage &) image).bits(); + int bpl = image.bytesPerLine() / 4; + for (int y=0; ylastUpdateWidget = widget; } else if (it->lastUpdateWidget == widget) { - // Update the gl wigets that the widget intersected the last time around, - // and that we are not intersecting now. This prevents paint errors when the + // Update the gl wigets that the widget intersected the last time around, + // and that we are not intersecting now. This prevents paint errors when the // intersecting widget leaves a gl widget. qt_post_window_change_event(glWidget); - it->lastUpdateWidget = 0; + it->lastUpdateWidget = 0; } } #else @@ -808,8 +829,8 @@ Q_GUI_EXPORT void qt_event_request_window_change(QWidget *widget) // Post a kEventQtRequestWindowChange event. This event is semi-public, // don't remove this line! qt_event_request_window_change(); - - // Post update request on gl widgets unconditionally. + + // Post update request on gl widgets unconditionally. if (qt_widget_private(widget)->isGLWidget == true) { qt_post_window_change_event(widget); return; @@ -1214,8 +1235,6 @@ void qt_init(QApplicationPrivate *priv, int) if (QApplication::desktopSettingsAware()) QApplicationPrivate::qt_mac_apply_settings(); - qt_mac_read_fontsmoothing_settings(); - // Cocoa application delegate #ifdef QT_MAC_USE_COCOA NSApplication *cocoaApp = [NSApplication sharedApplication]; @@ -1253,6 +1272,7 @@ void qt_init(QApplicationPrivate *priv, int) } priv->native_modal_dialog_active = false; + qt_mac_read_fontsmoothing_settings(); } void qt_release_apple_event_handler() @@ -1705,7 +1725,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event // kEventMouseWheelMoved events if we dont eat this event // (actually two events; one for horizontal and one for vertical). // As a results of this, and to make sure we dont't receive duplicate events, - // we try to detect when this happend by checking the 'compatibilityEvent'. + // we try to detect when this happend by checking the 'compatibilityEvent'. SInt32 mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); @@ -2576,7 +2596,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup delete QApplicationPrivate::popupWidgets; QApplicationPrivate::popupWidgets = 0; - + // Special case for Tool windows: since they are activated and deactived together // with a normal window they never become the QApplicationPrivate::active_window. QWidget *appFocusWidget = QApplication::focusWidget(); -- cgit v0.12 From aa2d3eb0f05dc87347e30fc0a6c843fc3d1b4855 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 21 Jan 2010 08:49:12 +0100 Subject: Don't use a mutex lock in QPainter::redirection unless strictly required --- src/gui/painting/qpainter.cpp | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a9dcea0..764ec68 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7385,10 +7385,15 @@ struct QPaintDeviceRedirection typedef QList QPaintDeviceRedirectionList; Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections) Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) +Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic) /*! \threadsafe + \obsolete + + Please use QWidget::render() instead. + Redirects all paint commands for the given paint \a device, to the \a replacement device. The optional point \a offset defines an offset within the source device. @@ -7398,9 +7403,10 @@ Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) device's painter (if any) before redirecting. Call restoreRedirected() to restore the previous redirection. - In general, you'll probably find that calling - QPixmap::grabWidget() or QPixmap::grabWindow() is an easier - solution. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. \sa redirected(), restoreRedirected() */ @@ -7432,14 +7438,24 @@ void QPainter::setRedirected(const QPaintDevice *device, Q_ASSERT(redirections != 0); *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset, hadInternalWidgetRedirection ? redirections->size() - 1 : -1); + globalRedirectionAtomic()->ref(); } /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Restores the previous redirection for the given \a device after a call to setRedirected(). + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa redirected() */ void QPainter::restoreRedirected(const QPaintDevice *device) @@ -7450,6 +7466,7 @@ void QPainter::restoreRedirected(const QPaintDevice *device) Q_ASSERT(redirections != 0); for (int i = redirections->size()-1; i >= 0; --i) { if (redirections->at(i) == device) { + globalRedirectionAtomic()->deref(); const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex; redirections->removeAt(i); // Restore the internal widget redirection, i.e. remove it from the global @@ -7471,21 +7488,34 @@ void QPainter::restoreRedirected(const QPaintDevice *device) /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Returns the replacement for given \a device. The optional out parameter \a offset returns the offset within the replaced device. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa setRedirected(), restoreRedirected() */ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) { Q_ASSERT(device != 0); + if (*globalRedirectionAtomic() == 0) + return 0; + if (device->devType() == QInternal::Widget) { const QWidgetPrivate *widgetPrivate = static_cast(device)->d_func(); if (widgetPrivate->redirectDev) return widgetPrivate->redirected(offset); } + QMutexLocker locker(globalRedirectionsMutex()); QPaintDeviceRedirectionList *redirections = globalRedirections(); Q_ASSERT(redirections != 0); @@ -7503,6 +7533,9 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { + if (*globalRedirectionAtomic() == 0) + return; + QMutex *mutex = 0; QT_TRY { mutex = globalRedirectionsMutex(); -- cgit v0.12 From 848ae6da25e567e9f64bc98dcbf868912448d136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Thu, 21 Jan 2010 10:32:14 +0100 Subject: Doc fixes: Remove some lies from QEasingCurve. Task-number: QTBUG-7418 --- src/corelib/tools/qeasingcurve.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 0ef92d9..b6a2df4 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -125,7 +125,7 @@ \value OutCubic \inlineimage qeasingcurve-outcubic.png \br Easing curve for a cubic (t^3) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png \br Easing curve for a cubic (t^3) function: @@ -141,7 +141,7 @@ \value OutQuart \inlineimage qeasingcurve-outquart.png \br Easing curve for a cubic (t^4) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutQuart \inlineimage qeasingcurve-inoutquart.png \br Easing curve for a cubic (t^4) function: @@ -157,7 +157,7 @@ \value OutQuint \inlineimage qeasingcurve-outquint.png \br Easing curve for a cubic (t^5) function: - decelerating from zero velocity. + decelerating to zero velocity. \value InOutQuint \inlineimage qeasingcurve-inoutquint.png \br Easing curve for a cubic (t^5) function: -- cgit v0.12 From 1729c2baea4e39f97d71b77f4c25af131f23221c Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 20 Jan 2010 08:59:48 +0100 Subject: Remove unnecessary depth uniform from GL2 engine's GLSL Reviewed-By: Samuel --- src/opengl/gl2paintengineex/qglengineshadersource_p.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index d9a61e9..6e98b02 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -64,23 +64,19 @@ QT_MODULE(OpenGL) static const char* const qglslMainVertexShader = "\ - uniform highp float depth;\ void setPosition();\ void main(void)\ {\ setPosition();\ - gl_Position.z = depth * gl_Position.w;\ }"; static const char* const qglslMainWithTexCoordsVertexShader = "\ attribute highp vec2 textureCoordArray; \ varying highp vec2 textureCoords; \ - uniform highp float depth;\ void setPosition();\ void main(void) \ {\ setPosition();\ - gl_Position.z = depth * gl_Position.w;\ textureCoords = textureCoordArray; \ }"; @@ -89,12 +85,10 @@ static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ attribute lowp float opacityArray; \ varying highp vec2 textureCoords; \ varying lowp float opacity; \ - uniform highp float depth; \ void setPosition(); \ void main(void) \ { \ setPosition(); \ - gl_Position.z = depth * gl_Position.w; \ textureCoords = textureCoordArray; \ opacity = opacityArray; \ }"; -- cgit v0.12 From 3a8236a01f89882d91e22a336f1e7134d3a84b68 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 20 Jan 2010 10:18:32 +0100 Subject: Use an attribute value for the PMV matrix rather than a uniform This has several advantages: First, updating an attribute value seems to be cheaper than updating a uniform. Second, vertex atribute values are independent of shader program, which means they persist across changing of the shader program. This makes code simpler and reduces GL state changes. Note: Credit goes to Samuel for finding this little gem. :-) For the 25920 solid QGraphicsRectItem test case, this gives 10% improvement on desktop and 27% on the SGX. Reviewed-By: Kim --- .../gl2paintengineex/qglengineshadermanager.cpp | 7 ++++- .../gl2paintengineex/qglengineshadermanager_p.h | 5 +++- .../gl2paintengineex/qglengineshadersource_p.h | 34 +++++++++++++++++----- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 25 ++++------------ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 2 -- 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 556b888..9fd9e18 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -324,6 +324,11 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); if (newProg->useOpacityAttribute) newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); + if (newProg->usePmvMatrix) { + newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); + newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); + newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); + } newProg->program->link(); if (!newProg->program->isLinked()) { @@ -424,7 +429,6 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id) "patternColor", "globalOpacity", "depth", - "pmvMatrix", "maskTexture", "fragmentColor", "linearData", @@ -743,6 +747,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() } requiredProgram.useTextureCoords = texCoords; requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); + requiredProgram.usePmvMatrix = true; // At this point, requiredProgram is fully populated so try to find the program in the cache currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index c52e5c0..3ab4ebe 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -253,6 +253,9 @@ struct QGLEngineCachedShaderProg static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; static const GLuint QT_OPACITY_ATTR = 2; +static const GLuint QT_PMV_MATRIX_1_ATTR = 3; +static const GLuint QT_PMV_MATRIX_2_ATTR = 4; +static const GLuint QT_PMV_MATRIX_3_ATTR = 5; class QGLEngineShaderProg; @@ -397,6 +400,7 @@ public: bool useTextureCoords; bool useOpacityAttribute; + bool usePmvMatrix; bool operator==(const QGLEngineShaderProg& other) { // We don't care about the program @@ -431,7 +435,6 @@ public: PatternColor, GlobalOpacity, Depth, - PmvMatrix, MaskTexture, FragmentColor, LinearData, diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 6e98b02..b471b81 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -97,9 +97,12 @@ static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ // shader are also perspective corrected. static const char* const qglslPositionOnlyVertexShader = "\ attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ void setPosition(void)\ {\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \ }"; @@ -114,12 +117,15 @@ static const char* const qglslUntransformedPositionVertexShader = "\ // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 static const char* const qglslPositionWithPatternBrushVertexShader = "\ attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 patternTexCoords; \ void setPosition(void) { \ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ @@ -144,12 +150,15 @@ static const char* const qglslPatternBrushSrcFragmentShader = "\ // Linear Gradient Brush static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec3 linearData; \ uniform highp mat3 brushTransform; \ varying mediump float index; \ void setPosition() { \ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ @@ -174,12 +183,15 @@ static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ // Conical Gradient Brush static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 A; \ - void setPosition(void)\ - {\ + void setPosition(void) \ + { \ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ @@ -210,7 +222,9 @@ static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ // Radial Gradient Brush static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ attribute highp vec2 vertexCoordsArray;\ - uniform highp mat3 pmvMatrix;\ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ uniform mediump vec2 halfViewportSize; \ uniform highp mat3 brushTransform; \ uniform highp vec2 fmp; \ @@ -218,6 +232,7 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ varying highp vec2 A; \ void setPosition(void) \ {\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ @@ -247,12 +262,15 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ // Texture Brush static const char* const qglslPositionWithTextureBrushVertexShader = "\ attribute highp vec2 vertexCoordsArray; \ - uniform highp mat3 pmvMatrix; \ + attribute highp vec3 pmvMatrix1; \ + attribute highp vec3 pmvMatrix2; \ + attribute highp vec3 pmvMatrix3; \ uniform mediump vec2 halfViewportSize; \ uniform highp vec2 invertedTextureSize; \ uniform highp mat3 brushTransform; \ varying highp vec2 textureCoords; \ void setPosition(void) { \ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ gl_Position.xy = transformedPos.xy / transformedPos.z; \ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index caa679b..b282676 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -168,12 +168,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader() if (matrixDirty) updateMatrix(); - - if (simpleShaderMatrixUniformDirty) { - const GLuint location = shaderManager->simpleProgram()->uniformLocation("pmvMatrix"); - glUniformMatrix3fv(location, 1, GL_FALSE, (GLfloat*)pmvMatrix); - simpleShaderMatrixUniformDirty = false; - } } void QGL2PaintEngineExPrivate::updateBrushTexture() @@ -392,9 +386,11 @@ void QGL2PaintEngineExPrivate::updateMatrix() matrixDirty = false; - // The actual data has been updated so both shader program's uniforms need updating - simpleShaderMatrixUniformDirty = true; - shaderMatrixUniformDirty = true; + // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only + // need to do this once for every matrix change and persists across all shader programs. + glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]); + glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]); + glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]); dasher.setInvScale(inverseScale); stroker.setInvScale(inverseScale); @@ -932,18 +928,12 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) if (changed) { // The shader program has changed so mark all uniforms as dirty: brushUniformsDirty = true; - shaderMatrixUniformDirty = true; opacityUniformDirty = true; } if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode) updateBrushUniforms(); - if (shaderMatrixUniformDirty) { - glUniformMatrix3fv(location(QGLEngineShaderManager::PmvMatrix), 1, GL_FALSE, (GLfloat*)pmvMatrix); - shaderMatrixUniformDirty = false; - } - if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) { shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); opacityUniformDirty = false; @@ -1955,11 +1945,8 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state == s || old_state->renderHintsChanged) renderHintsChanged(); - if (old_state == s || old_state->matrixChanged) { + if (old_state == s || old_state->matrixChanged) d->matrixDirty = true; - d->simpleShaderMatrixUniformDirty = true; - d->shaderMatrixUniformDirty = true; - } if (old_state == s || old_state->compositionModeChanged) d->compositionModeDirty = true; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index ce1b538..8fa0eff 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -252,8 +252,6 @@ public: bool compositionModeDirty; bool brushTextureDirty; bool brushUniformsDirty; - bool simpleShaderMatrixUniformDirty; - bool shaderMatrixUniformDirty; bool opacityUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? -- cgit v0.12 From 87ca0fa9389b7ef77e179b6db7ddc970b7228d6c Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 20 Jan 2010 12:47:18 +0100 Subject: Purely cosmetic (formatting) changes to GL2 engine's GLSL This makes GLSL dumps _significantly_ easier to read. Reviewed-By: TrustMe --- .../gl2paintengineex/qglengineshadersource_p.h | 690 +++++++++++---------- 1 file changed, 357 insertions(+), 333 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index b471b81..ee04166 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -63,222 +63,229 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) -static const char* const qglslMainVertexShader = "\ - void setPosition();\ - void main(void)\ - {\ - setPosition();\ - }"; - -static const char* const qglslMainWithTexCoordsVertexShader = "\ - attribute highp vec2 textureCoordArray; \ - varying highp vec2 textureCoords; \ - void setPosition();\ - void main(void) \ - {\ - setPosition();\ - textureCoords = textureCoordArray; \ - }"; - -static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\ - attribute highp vec2 textureCoordArray; \ - attribute lowp float opacityArray; \ - varying highp vec2 textureCoords; \ - varying lowp float opacity; \ - void setPosition(); \ - void main(void) \ - { \ - setPosition(); \ - textureCoords = textureCoordArray; \ - opacity = opacityArray; \ - }"; +static const char* const qglslMainVertexShader = "\n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + }\n"; + +static const char* const qglslMainWithTexCoordsVertexShader = "\n\ + attribute highp vec2 textureCoordArray; \n\ + varying highp vec2 textureCoords; \n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + textureCoords = textureCoordArray; \n\ + }\n"; + +static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\n\ + attribute highp vec2 textureCoordArray; \n\ + attribute lowp float opacityArray; \n\ + varying highp vec2 textureCoords; \n\ + varying lowp float opacity; \n\ + void setPosition(); \n\ + void main(void) \n\ + { \n\ + setPosition(); \n\ + textureCoords = textureCoordArray; \n\ + opacity = opacityArray; \n\ + }\n"; // NOTE: We let GL do the perspective correction so texture lookups in the fragment // shader are also perspective corrected. -static const char* const qglslPositionOnlyVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - void setPosition(void)\ - {\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \ - }"; - -static const char* const qglslUntransformedPositionVertexShader = "\ - attribute highp vec4 vertexCoordsArray;\ - void setPosition(void)\ - {\ - gl_Position = vertexCoordsArray;\ - }"; +static const char* const qglslPositionOnlyVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ + }\n"; + +static const char* const qglslUntransformedPositionVertexShader = "\n\ + attribute highp vec4 vertexCoordsArray; \n\ + void setPosition(void) \n\ + { \n\ + gl_Position = vertexCoordsArray; \n\ + }\n"; // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 -static const char* const qglslPositionWithPatternBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec2 invertedTextureSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 patternTexCoords; \ - void setPosition(void) { \ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithPatternBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec2 invertedTextureSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 patternTexCoords; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithPatternBrushVertexShader = qglslPositionWithPatternBrushVertexShader; -static const char* const qglslPatternBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture;\ - uniform lowp vec4 patternColor; \ - varying highp vec2 patternTexCoords;\ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \ +static const char* const qglslPatternBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + uniform lowp vec4 patternColor; \n\ + varying highp vec2 patternTexCoords;\n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\ }\n"; // Linear Gradient Brush -static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec3 linearData; \ - uniform highp mat3 brushTransform; \ - varying mediump float index; \ - void setPosition() { \ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec3 linearData; \n\ + uniform highp mat3 brushTransform; \n\ + varying mediump float index; \n\ + void setPosition() \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader = qglslPositionWithLinearGradientBrushVertexShader; -static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture; \ - varying mediump float index; \ - lowp vec4 srcPixel() { \ - mediump vec2 val = vec2(index, 0.5); \ - return texture2D(brushTexture, val); \ +static const char* const qglslLinearGradientBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + varying mediump float index; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + mediump vec2 val = vec2(index, 0.5); \n\ + return texture2D(brushTexture, val); \n\ }\n"; // Conical Gradient Brush -static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 A; \ - void setPosition(void) \ - { \ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - A = hTexCoords.xy * invertedHTexCoordsZ; \ - }"; +static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 A; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + A = hTexCoords.xy * invertedHTexCoordsZ; \n\ + }\n"; static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader = qglslPositionWithConicalGradientBrushVertexShader; static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ #define INVERSE_2PI 0.1591549430918953358 \n\ - uniform lowp sampler2D brushTexture; \n\ - uniform mediump float angle; \ - varying highp vec2 A; \ - lowp vec4 srcPixel() { \ - highp float t; \ - if (abs(A.y) == abs(A.x)) \ - t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \ - else \ - t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \ - return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \ - }"; + uniform lowp sampler2D brushTexture; \n\ + uniform mediump float angle; \n\ + varying highp vec2 A; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + highp float t; \n\ + if (abs(A.y) == abs(A.x)) \n\ + t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ + else \n\ + t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ + return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\ + }\n"; // Radial Gradient Brush -static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray;\ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp mat3 brushTransform; \ - uniform highp vec2 fmp; \ - varying highp float b; \ - varying highp vec2 A; \ - void setPosition(void) \ - {\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - A = hTexCoords.xy * invertedHTexCoordsZ; \ - b = 2.0 * dot(A, fmp); \ - }"; +static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray;\n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp mat3 brushTransform; \n\ + uniform highp vec2 fmp; \n\ + varying highp float b; \n\ + varying highp vec2 A; \n\ + void setPosition(void) \n\ + {\n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + A = hTexCoords.xy * invertedHTexCoordsZ; \n\ + b = 2.0 * dot(A, fmp); \n\ + }\n"; static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader = qglslPositionWithRadialGradientBrushVertexShader; -static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ - uniform lowp sampler2D brushTexture; \ - uniform highp float fmp2_m_radius2; \ - uniform highp float inverse_2_fmp2_m_radius2; \ - varying highp float b; \ - varying highp vec2 A; \ - lowp vec4 srcPixel() { \ - highp float c = -dot(A, A); \ - highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \ - return texture2D(brushTexture, val); \ - }"; +static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\ + uniform lowp sampler2D brushTexture; \n\ + uniform highp float fmp2_m_radius2; \n\ + uniform highp float inverse_2_fmp2_m_radius2; \n\ + varying highp float b; \n\ + varying highp vec2 A; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + highp float c = -dot(A, A); \n\ + highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \n\ + return texture2D(brushTexture, val); \n\ + }\n"; // Texture Brush -static const char* const qglslPositionWithTextureBrushVertexShader = "\ - attribute highp vec2 vertexCoordsArray; \ - attribute highp vec3 pmvMatrix1; \ - attribute highp vec3 pmvMatrix2; \ - attribute highp vec3 pmvMatrix3; \ - uniform mediump vec2 halfViewportSize; \ - uniform highp vec2 invertedTextureSize; \ - uniform highp mat3 brushTransform; \ - varying highp vec2 textureCoords; \ - void setPosition(void) { \ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \ - gl_Position.xy = transformedPos.xy / transformedPos.z; \ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \ - textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \ - }"; +static const char* const qglslPositionWithTextureBrushVertexShader = "\n\ + attribute highp vec2 vertexCoordsArray; \n\ + attribute highp vec3 pmvMatrix1; \n\ + attribute highp vec3 pmvMatrix2; \n\ + attribute highp vec3 pmvMatrix3; \n\ + uniform mediump vec2 halfViewportSize; \n\ + uniform highp vec2 invertedTextureSize; \n\ + uniform highp mat3 brushTransform; \n\ + varying highp vec2 textureCoords; \n\ + void setPosition(void) \n\ + { \n\ + highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ + vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ + gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ + mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ + mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ + mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ + gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ + textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ + }\n"; static const char* const qglslAffinePositionWithTextureBrushVertexShader = qglslPositionWithTextureBrushVertexShader; @@ -287,148 +294,165 @@ static const char* const qglslAffinePositionWithTextureBrushVertexShader // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, // we emulate GL_REPEAT by only taking the fractional part of the texture coords. // TODO: Special case POT textures which don't need this emulation -static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(brushTexture, fract(textureCoords)); \ - }"; +static const char* const qglslTextureBrushSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() { \n\ + return texture2D(brushTexture, fract(textureCoords)); \n\ + }\n"; #else -static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(brushTexture, textureCoords); \ - }"; +static const char* const qglslTextureBrushSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return texture2D(brushTexture, textureCoords); \n\ + }\n"; #endif -static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp vec4 patternColor; \ - uniform lowp sampler2D brushTexture; \ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \ - }"; +static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp vec4 patternColor; \n\ + uniform lowp sampler2D brushTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \n\ + }\n"; // Solid Fill Brush -static const char* const qglslSolidBrushSrcFragmentShader = "\ - uniform lowp vec4 fragmentColor; \ - lowp vec4 srcPixel() { \ - return fragmentColor; \ - }"; - -static const char* const qglslImageSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - return texture2D(imageTexture, textureCoords); \ - }"; - -static const char* const qglslCustomSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \ - lowp vec4 srcPixel() { \ - return customShader(imageTexture, textureCoords); \ - }"; - -static const char* const qglslImageSrcWithPatternFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp vec4 patternColor; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \ - }\n"; - -static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ - uniform lowp sampler2D imageTexture; \ - lowp vec4 srcPixel() { \ - lowp vec4 sample = texture2D(imageTexture, textureCoords); \ - sample.rgb = sample.rgb * sample.a; \ - return sample; \ - }"; - -static const char* const qglslShockingPinkSrcFragmentShader = "\ - lowp vec4 srcPixel() { \ - return vec4(0.98, 0.06, 0.75, 1.0); \ - }"; - -static const char* const qglslMainFragmentShader_ImageArrays = "\ - varying lowp float opacity; \ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel() * opacity; \ - }"; - -static const char* const qglslMainFragmentShader_CMO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \ - }"; - -static const char* const qglslMainFragmentShader_CM = "\ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(compose(srcPixel())); \ - }"; - -static const char* const qglslMainFragmentShader_MO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(srcPixel()*globalOpacity); \ - }"; - -static const char* const qglslMainFragmentShader_M = "\ - lowp vec4 srcPixel(); \ - lowp vec4 applyMask(lowp vec4); \ - void main() { \ - gl_FragColor = applyMask(srcPixel()); \ - }"; - -static const char* const qglslMainFragmentShader_CO = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = compose(srcPixel()*globalOpacity); \ - }"; - -static const char* const qglslMainFragmentShader_C = "\ - lowp vec4 srcPixel(); \ - lowp vec4 compose(lowp vec4); \ - void main() { \ - gl_FragColor = compose(srcPixel()); \ - }"; - -static const char* const qglslMainFragmentShader_O = "\ - uniform lowp float globalOpacity; \ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel()*globalOpacity; \ - }"; - -static const char* const qglslMainFragmentShader = "\ - lowp vec4 srcPixel(); \ - void main() { \ - gl_FragColor = srcPixel(); \ - }"; - -static const char* const qglslMaskFragmentShader = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src * mask.a; \ - }"; +static const char* const qglslSolidBrushSrcFragmentShader = "\n\ + uniform lowp vec4 fragmentColor; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return fragmentColor; \n\ + }\n"; + +static const char* const qglslImageSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return texture2D(imageTexture, textureCoords); \n\ + }\n"; + +static const char* const qglslCustomSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return customShader(imageTexture, textureCoords); \n\ + }\n"; + +static const char* const qglslImageSrcWithPatternFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp vec4 patternColor; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\ + }\n"; + +static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\n\ + varying highp vec2 textureCoords; \n\ + uniform lowp sampler2D imageTexture; \n\ + lowp vec4 srcPixel() \n\ + { \n\ + lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\ + sample.rgb = sample.rgb * sample.a; \n\ + return sample; \n\ + }\n"; + +static const char* const qglslShockingPinkSrcFragmentShader = "\n\ + lowp vec4 srcPixel() \n\ + { \n\ + return vec4(0.98, 0.06, 0.75, 1.0); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_ImageArrays = "\n\ + varying lowp float opacity; \n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel() * opacity; \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CMO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CM = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(compose(srcPixel())); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_MO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_M = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 applyMask(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = applyMask(srcPixel()); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_CO = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = compose(srcPixel()*globalOpacity); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_C = "\n\ + lowp vec4 srcPixel(); \n\ + lowp vec4 compose(lowp vec4); \n\ + void main() \n\ + { \n\ + gl_FragColor = compose(srcPixel()); \n\ + }\n"; + +static const char* const qglslMainFragmentShader_O = "\n\ + uniform lowp float globalOpacity; \n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel()*globalOpacity; \n\ + }\n"; + +static const char* const qglslMainFragmentShader = "\n\ + lowp vec4 srcPixel(); \n\ + void main() \n\ + { \n\ + gl_FragColor = srcPixel(); \n\ + }\n"; + +static const char* const qglslMaskFragmentShader = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + {\n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src * mask.a; \n\ + }\n"; // For source over with subpixel antialiasing, the final color is calculated per component as follows // (.a is alpha component, .c is red, green or blue component): @@ -445,23 +469,23 @@ static const char* const qglslMaskFragmentShader = "\ // dest.c = dest.c * (1 - mask.c) + src.c * alpha // -static const char* const qglslRgbMaskFragmentShaderPass1 = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src.a * mask; \ - }"; - -static const char* const qglslRgbMaskFragmentShaderPass2 = "\ - varying highp vec2 textureCoords;\ - uniform lowp sampler2D maskTexture;\ - lowp vec4 applyMask(lowp vec4 src) \ - {\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \ - return src * mask; \ - }"; +static const char* const qglslRgbMaskFragmentShaderPass1 = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + { \n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src.a * mask; \n\ + }\n"; + +static const char* const qglslRgbMaskFragmentShaderPass2 = "\n\ + varying highp vec2 textureCoords;\n\ + uniform lowp sampler2D maskTexture;\n\ + lowp vec4 applyMask(lowp vec4 src) \n\ + { \n\ + lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ + return src * mask; \n\ + }\n"; /* Left to implement: -- cgit v0.12 From 06ee48f7ad7f5ab8bdbaed765d301fa2c0b417fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Thu, 21 Jan 2010 15:54:18 +0100 Subject: Make sure cursor is painted at the correct position when we are using IM. When the line edit was refactored into a line control this regression was introduced. This regression was introduced by change fb7d86cf23227302d48db279ec589221d11a1f6a. Task-number: QTBUG-4789 Reviewed-by: Alan Alpert --- src/gui/widgets/qlinecontrol.cpp | 5 ++++- src/gui/widgets/qlinecontrol_p.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 414c2ed..b0a64ea 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -524,8 +524,11 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl m_textLayout.draw(painter, offset, selections, clip); if (flags & DrawCursor){ + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; if(!m_blinkPeriod || m_blinkStatus) - m_textLayout.drawCursor(painter, offset, m_cursor, m_cursorWidth); + m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth); } } diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 301ff72..d6f2705 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -549,7 +549,10 @@ inline qreal QLineControl::cursorToX(int cursor) const inline qreal QLineControl::cursorToX() const { - return cursorToX(m_cursor); + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; + return cursorToX(cursor); } inline bool QLineControl::isReadOnly() const -- cgit v0.12 From 474e0dce59e827e4dd502bf12e7817b2602fb2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 13 Jan 2010 16:44:57 +0100 Subject: Improve performance of QGraphicsItem::setParentItem. The biggest optimization here is "updateAncestorFlags()". It's much faster to update all the flags rather than trying to enable/disable certain flags according to the current state. Task-number: QTBUG-6877 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 67 ++++++++++++++++++++++----------- src/gui/graphicsview/qgraphicsitem_p.h | 9 +++-- src/gui/graphicsview/qgraphicsscene.cpp | 21 ++++++----- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 1361a89..541df7c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -798,8 +798,36 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch return; } - foreach (QGraphicsItem *child, children) - child->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false); + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->updateAncestorFlag(childFlag, flag, enabled, false); +} + +void QGraphicsItemPrivate::updateAncestorFlags() +{ + int flags = 0; + if (parent) { + // Inherit the parent's ancestor flags. + QGraphicsItemPrivate *pd = parent->d_ptr.data(); + flags = pd->ancestorFlags; + + // Add in flags from the parent. + if (pd->filtersDescendantEvents) + flags |= AncestorFiltersChildEvents; + if (pd->handlesChildEvents) + flags |= AncestorHandlesChildEvents; + if (pd->flags & QGraphicsItem::ItemClipsChildrenToShape) + flags |= AncestorClipsChildren; + if (pd->flags & QGraphicsItem::ItemIgnoresTransformations) + flags |= AncestorIgnoresTransformations; + } + + if (ancestorFlags == flags) + return; // No change; stop propagation. + ancestorFlags = flags; + + // Propagate to children recursively. + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->updateAncestorFlags(); } /*! @@ -1002,7 +1030,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (scene) { // Deliver the change to the index - scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex) + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); // Disable scene pos notifications for old ancestors if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) @@ -1042,7 +1071,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *p = parent; QGraphicsItem *parentFocusScopeItem = 0; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { // If this item's focus scope's focus scope item points // to this item or a descendent, then clear it. QGraphicsItem *fsi = p->d_ptr->focusScopeItem; @@ -1063,11 +1092,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *ancestorScope = 0; QGraphicsItem *p = subFocusItem->d_ptr->parent; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) ancestorScope = p; - if (p->isPanel()) + if (p->d_ptr->flags & QGraphicsItem::ItemIsPanel) break; - p = p->parentItem(); + p = p->d_ptr->parent; } if (ancestorScope) newFocusScopeItem = ancestorScope; @@ -1075,7 +1104,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *p = newParent; while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->focusScopeItem = newFocusScopeItem; // Ensure the new item is no longer the subFocusItem. The // only way to set focus on a child of a focus scope is @@ -1111,30 +1140,24 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Inherit ancestor flags from the new parent. - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); - updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); - updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); + updateAncestorFlags(); // Update item visible / enabled. - if (parent->isVisible() != visible) { - if (!parent->isVisible() || !explicitlyHidden) - setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate); + if (parent->d_ptr->visible != visible) { + if (!parent->d_ptr->visible || !explicitlyHidden) + setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ !implicitUpdate); } if (parent->isEnabled() != enabled) { - if (!parent->isEnabled() || !explicitlyDisabled) - setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate); + if (!parent->d_ptr->enabled || !explicitlyDisabled) + setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ !implicitUpdate); } // Auto-activate if visible and the parent is active. - if (q->isVisible() && parent->isActive()) + if (visible && parent->isActive()) q->setActive(true); } else { // Inherit ancestor flags from the new parent. - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); - updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); - updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); - updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); + updateAncestorFlags(); if (!inDestructor) { // Update item visible / enabled. diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 2d34b80..cfdd382 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -153,7 +153,7 @@ public: dirtyChildren(0), localCollisionHack(0), inSetPosHelper(0), - needSortChildren(1), // ### can be 0 by default? + needSortChildren(0), allChildrenDirty(0), fullUpdatePending(0), flags(0), @@ -197,6 +197,7 @@ public: void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); + void updateAncestorFlags(); void setIsMemberOfGroup(bool enabled); void remapItemPos(QEvent *event, QGraphicsItem *item); QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; @@ -721,11 +722,13 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const inline void QGraphicsItemPrivate::ensureSortedChildren() { if (needSortChildren) { - qSort(children.begin(), children.end(), qt_notclosestLeaf); needSortChildren = 0; sequentialOrdering = 1; + if (children.isEmpty()) + return; + qSort(children.begin(), children.end(), qt_notclosestLeaf); for (int i = 0; i < children.size(); ++i) { - if (children[i]->d_ptr->siblingIndex != i) { + if (children.at(i)->d_ptr->siblingIndex != i) { sequentialOrdering = 0; break; } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index cea723c..49925e1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2482,12 +2482,12 @@ void QGraphicsScene::addItem(QGraphicsItem *item) qWarning("QGraphicsScene::addItem: cannot add null item"); return; } - if (item->scene() == this) { + if (item->d_ptr->scene == this) { qWarning("QGraphicsScene::addItem: item has already been added to this scene"); return; } // Remove this item from its existing scene - if (QGraphicsScene *oldScene = item->scene()) + if (QGraphicsScene *oldScene = item->d_ptr->scene) oldScene->removeItem(item); // Notify the item that its scene is changing, and allow the item to @@ -2496,15 +2496,15 @@ void QGraphicsScene::addItem(QGraphicsItem *item) qVariantFromValue(this))); QGraphicsScene *targetScene = qVariantValue(newSceneVariant); if (targetScene != this) { - if (targetScene && item->scene() != targetScene) + if (targetScene && item->d_ptr->scene != targetScene) targetScene->addItem(item); return; } // Detach this item from its parent if the parent's scene is different // from this scene. - if (QGraphicsItem *itemParent = item->parentItem()) { - if (itemParent->scene() != this) + if (QGraphicsItem *itemParent = item->d_ptr->parent) { + if (itemParent->d_ptr->scene != this) item->setParentItem(0); } @@ -2534,7 +2534,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) d->enableMouseTrackingOnViews(); } #ifndef QT_NO_CURSOR - if (d->allItemsUseDefaultCursor && item->hasCursor()) { + if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) { d->allItemsUseDefaultCursor = false; if (d->allItemsIgnoreHoverEvents) // already enabled otherwise d->enableMouseTrackingOnViews(); @@ -2542,7 +2542,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) #endif //QT_NO_CURSOR // Enable touch events if the item accepts touch events. - if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) { + if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) { d->allItemsIgnoreTouchEvents = false; d->enableTouchEventsOnViews(); } @@ -2575,8 +2575,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) } // Add all children recursively - foreach (QGraphicsItem *child, item->children()) - addItem(child); + item->d_ptr->ensureSortedChildren(); + for (int i = 0; i < item->d_ptr->children.size(); ++i) + addItem(item->d_ptr->children.at(i)); // Resolve font and palette. item->d_ptr->resolveFont(d->font.resolve()); @@ -2619,7 +2620,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) } } - if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) + if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges) d->registerScenePosItem(item); // Ensure that newly added items that have subfocus set, gain -- cgit v0.12 From dc3005761d332f86d59257e2c6bb8aac70222b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 14 Jan 2010 11:43:05 +0100 Subject: Optimize QGraphicsScenePrivate::itemAcceptsHoverEvents_helper Make sure we do cheap tests before the more expensive ones. This function is called from QGraphicsScene::addItem. Task-number: QTBUG-6877 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsscene.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 49925e1..fa9f794 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3767,10 +3767,10 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const { - return (!item->isBlockedByModalPanel() && - (item->acceptHoverEvents() - || (item->isWidget() - && static_cast(item)->d_func()->hasDecoration()))); + return (item->d_ptr->acceptsHover + || (item->d_ptr->isWidget + && static_cast(item)->d_func()->hasDecoration())) + && !item->isBlockedByModalPanel(); } /*! -- cgit v0.12 From 0dd05278e91ca1b0f4ffd32195584a57064ed24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 14 Jan 2010 16:13:37 +0100 Subject: Optimize QGraphicsItem::setFlags. We don't have to do a full blown QGraphicsItem::setFlag call from QGraphicsItem::setFlags, only to change the ItemStacksBehindParent bits. We can do it directly (with care). Task-number: QTBUG-6877 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 541df7c..8d77fcb 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1630,7 +1630,7 @@ bool QGraphicsItem::isWidget() const */ bool QGraphicsItem::isWindow() const { - return isWidget() && (static_cast(this)->windowType() & Qt::Window); + return d_ptr->isWidget && (static_cast(this)->windowType() & Qt::Window); } /*! @@ -1667,9 +1667,9 @@ QGraphicsItem::GraphicsItemFlags QGraphicsItem::flags() const void QGraphicsItem::setFlag(GraphicsItemFlag flag, bool enabled) { if (enabled) - setFlags(flags() | flag); + setFlags(GraphicsItemFlags(d_ptr->flags) | flag); else - setFlags(flags() & ~flag); + setFlags(GraphicsItemFlags(d_ptr->flags) & ~flag); } /*! @@ -1716,7 +1716,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); if (quint32(d_ptr->flags) == quint32(flags)) return; - if (d_ptr->scene) + if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). @@ -1726,7 +1726,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->paintedViewBoundingRectsNeedRepaint = 1; // Keep the old flags to compare the diff. - GraphicsItemFlags oldFlags = this->flags(); + GraphicsItemFlags oldFlags = GraphicsItemFlags(d_ptr->flags); // Update flags. d_ptr->flags = flags; @@ -1755,7 +1755,23 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->updateAncestorFlag(ItemIgnoresTransformations); } + if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { + // NB! We change the flags directly here, so we must also update d_ptr->flags. + // Note that this has do be done before the ItemStacksBehindParent check + // below; otherwise we will loose the change. + + // Update stack-behind. + if (d_ptr->z < qreal(0.0)) + flags |= ItemStacksBehindParent; + else + flags &= ~ItemStacksBehindParent; + d_ptr->flags = flags; + } + if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) { + // NB! This check has to come after the ItemNegativeZStacksBehindParent + // check above. Be careful. + // Ensure child item sorting is up to date when toggling this flag. if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; @@ -1769,10 +1785,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); } - if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { - // Update stack-behind. - setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0)); - } if ((d_ptr->panelModality != NonModal) && d_ptr->scene -- cgit v0.12 From b5754f5bd28ed01979e94983ae0480e913649d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 19 Jan 2010 13:18:55 +0100 Subject: Pass value as const void *const to QGraphicsSceneIndex::itemChange. We need this change in order to bypass some of the QVariant itemChange notifications from QGraphicsItem::setParentItem. All this is internal stuff and we know what we do, so I don't consider the change too ugly. Task-number: QTBUG-6877 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 8 ++++---- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 10 +++++----- src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 8d77fcb..5c7ea76 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1031,7 +1031,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (scene) { // Deliver the change to the index if (scene->d_func()->indexMethod != QGraphicsScene::NoIndex) - scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParent); // Disable scene pos notifications for old ancestors if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) @@ -1717,7 +1717,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) if (quint32(d_ptr->flags) == quint32(flags)) return; if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) - d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); + d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, &flags); // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); @@ -4299,9 +4299,9 @@ void QGraphicsItem::setZValue(qreal z) if (newZ == d_ptr->z) return; - if (d_ptr->scene) { + if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex) { // Z Value has changed, we have to notify the index. - d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); + d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ); } d_ptr->z = newZ; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 2e92b87..2a91348 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -635,16 +635,17 @@ void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) This method react to the \a change of the \a item and use the \a value to update the BSP tree if necessary. */ -void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) { Q_D(QGraphicsSceneBspTreeIndex); switch (change) { case QGraphicsItem::ItemFlagsChange: { // Handle ItemIgnoresTransformations + QGraphicsItem::GraphicsItemFlags newFlags = *static_cast(value); bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations; - bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; + bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations; bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; - bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape; + bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape; if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) { QGraphicsItem *thatItem = const_cast(item); // Remove item and its descendants from the index and append @@ -661,7 +662,7 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics case QGraphicsItem::ItemParentChange: { d->invalidateSortCache(); // Handle ItemIgnoresTransformations - QGraphicsItem *newParent = qVariantValue(value); + const QGraphicsItem *newParent = static_cast(value); bool ignoredTransform = item->d_ptr->itemIsUntransformable(); bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); @@ -682,7 +683,6 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics default: break; } - return QGraphicsSceneIndex::itemChange(item, change, value); } /*! \reimp diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 119571b..f671fd9 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -97,7 +97,7 @@ protected: void removeItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value); private : Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index bc8a7dc..043c4eb 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -624,7 +624,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa QGraphicsItem::GraphicsItemChange */ -void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value) { Q_UNUSED(item); Q_UNUSED(change); diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index def58f0..597a229 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -110,7 +110,7 @@ protected: virtual void removeItem(QGraphicsItem *item) = 0; virtual void deleteItem(QGraphicsItem *item); - virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const void *const value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene); -- cgit v0.12 From 3c215a1644adcca32cfc451456b6891f9c8519fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 19 Jan 2010 13:30:55 +0100 Subject: Only send QGraphicsItem::ParentChange(d) notifications from setParentItem. QmlGraphicsItem doesn't need any parent change notifactions so we can call the helper class (QGraphicsItemPrivate::setParentItemHelper) direclty from QmlGraphicsItem::setParentItem. This avoids a lot of unnecessary instructions related to QVariant constructions as well as virtual function calls. I've made the variant pointers explicit in the declaration of setParentItemHelper so that we don't accidentally call setParentItemHelper from places where we need parent change notifications. Task-number: QTBUG-6877 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 43 +++++++++++++++++++-------------- src/gui/graphicsview/qgraphicsitem_p.h | 3 ++- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5c7ea76..d43176b 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1012,19 +1012,10 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query prepareGeometryChange) if the item is in its destructor, i.e. inDestructor is 1. */ -void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) +void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const QVariant *newParentVariant, + const QVariant *thisPointerVariant) { Q_Q(QGraphicsItem); - if (newParent == q) { - qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); - return; - } - if (newParent == parent) - return; - - const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue(newParent))); - newParent = qVariantValue(newParentVariant); if (newParent == parent) return; @@ -1049,11 +1040,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (!inDestructor) q_ptr->prepareGeometryChange(); - const QVariant thisPointerVariant(qVariantFromValue(q)); if (parent) { // Remove from current parent parent->d_ptr->removeChild(q); - parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant); + if (thisPointerVariant) + parent->itemChange(QGraphicsItem::ItemChildRemovedChange, *thisPointerVariant); } // Update toplevelitem list. If this item is being deleted, its parent @@ -1129,7 +1120,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } parent->d_ptr->addChild(q); - parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant); + if (thisPointerVariant) + parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant); if (scene) { if (!implicitUpdate) scene->d_func()->markDirty(q_ptr); @@ -1184,7 +1176,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Deliver post-change notification - q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + if (newParentVariant) + q->itemChange(QGraphicsItem::ItemParentHasChanged, *newParentVariant); if (isObject) emit static_cast(q)->parentChanged(); @@ -1373,7 +1366,7 @@ QGraphicsItem::~QGraphicsItem() d_ptr->scene->d_func()->removeItemHelper(this); } else { d_ptr->resetFocusProxy(); - d_ptr->setParentItemHelper(0); + setParentItem(0); } #ifndef QT_NO_GRAPHICSEFFECT @@ -1578,9 +1571,23 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const \sa parentItem(), childItems() */ -void QGraphicsItem::setParentItem(QGraphicsItem *parent) +void QGraphicsItem::setParentItem(QGraphicsItem *newParent) { - d_ptr->setParentItemHelper(parent); + if (newParent == this) { + qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this); + return; + } + if (newParent == d_ptr->parent) + return; + + const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, + qVariantFromValue(newParent))); + newParent = qVariantValue(newParentVariant); + if (newParent == d_ptr->parent) + return; + + const QVariant thisPointerVariant(qVariantFromValue(this)); + d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index cfdd382..ac10aa7 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -230,7 +230,8 @@ public: void resolveDepth(); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); - void setParentItemHelper(QGraphicsItem *parent); + void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant, + const QVariant *thisPointerVariant); void childrenBoundingRectHelper(QTransform *x, QRectF *rect); void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, const QRegion &exposedRegion, bool allItems = false) const; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index fa9f794..088a6b9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -599,7 +599,7 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) if (parentItem->scene()) { Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem", "Parent item's scene is different from this item's scene"); - item->d_ptr->setParentItemHelper(0); + item->setParentItem(0); } } else { unregisterTopLevelItem(item); -- cgit v0.12 From 57c7df82ffbace8924c7ac8875ef4343783a2376 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 21 Jan 2010 08:49:12 +0100 Subject: Don't use a mutex lock in QPainter::redirection unless strictly required Reviewed-by: Trond --- src/gui/painting/qpainter.cpp | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 31132d9..1258d6b 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7382,10 +7382,15 @@ struct QPaintDeviceRedirection typedef QList QPaintDeviceRedirectionList; Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections) Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) +Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic) /*! \threadsafe + \obsolete + + Please use QWidget::render() instead. + Redirects all paint commands for the given paint \a device, to the \a replacement device. The optional point \a offset defines an offset within the source device. @@ -7395,9 +7400,10 @@ Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex) device's painter (if any) before redirecting. Call restoreRedirected() to restore the previous redirection. - In general, you'll probably find that calling - QPixmap::grabWidget() or QPixmap::grabWindow() is an easier - solution. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. \sa redirected(), restoreRedirected() */ @@ -7429,14 +7435,24 @@ void QPainter::setRedirected(const QPaintDevice *device, Q_ASSERT(redirections != 0); *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset, hadInternalWidgetRedirection ? redirections->size() - 1 : -1); + globalRedirectionAtomic()->ref(); } /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Restores the previous redirection for the given \a device after a call to setRedirected(). + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa redirected() */ void QPainter::restoreRedirected(const QPaintDevice *device) @@ -7447,6 +7463,7 @@ void QPainter::restoreRedirected(const QPaintDevice *device) Q_ASSERT(redirections != 0); for (int i = redirections->size()-1; i >= 0; --i) { if (redirections->at(i) == device) { + globalRedirectionAtomic()->deref(); const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex; redirections->removeAt(i); // Restore the internal widget redirection, i.e. remove it from the global @@ -7468,21 +7485,34 @@ void QPainter::restoreRedirected(const QPaintDevice *device) /*! \threadsafe + \obsolete + + Using QWidget::render() obsoletes the use of this function. + Returns the replacement for given \a device. The optional out parameter \a offset returns the offset within the replaced device. + \warning Making use of redirections in the QPainter API implies + that QPainter::begin() and QPaintDevice destructors need to hold + a mutex for a short period. This can impact performance. Use of + QWidget::render is strongly encouraged. + \sa setRedirected(), restoreRedirected() */ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) { Q_ASSERT(device != 0); + if (*globalRedirectionAtomic() == 0) + return 0; + if (device->devType() == QInternal::Widget) { const QWidgetPrivate *widgetPrivate = static_cast(device)->d_func(); if (widgetPrivate->redirectDev) return widgetPrivate->redirected(offset); } + QMutexLocker locker(globalRedirectionsMutex()); QPaintDeviceRedirectionList *redirections = globalRedirections(); Q_ASSERT(redirections != 0); @@ -7500,6 +7530,9 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) void qt_painter_removePaintDevice(QPaintDevice *dev) { + if (*globalRedirectionAtomic() == 0) + return; + QMutex *mutex = 0; QT_TRY { mutex = globalRedirectionsMutex(); -- cgit v0.12 From 03c77ad02d5a3c69f4edfdfd2f3ef7cd7dc67aaa Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 22 Jan 2010 08:31:32 +0100 Subject: Fix documentation bug in QColor --- src/gui/painting/qcolor.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index f51dc36..d6d288e 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -934,8 +934,7 @@ void QColor::setRgb(int r, int g, int b, int a) /*! \fn QRgb QColor::rgba() const - Returns the RGB value of the color. Unlike rgb(), the alpha is not - stripped. + Returns the RGB value of the color, including its alpha. For an invalid color, the alpha value of the returned color is unspecified. @@ -950,8 +949,7 @@ QRgb QColor::rgba() const } /*! - Sets the RGBA value to \a rgba. Unlike setRgb(QRgb rgb), this function does - not ignore the alpha. + Sets the RGB value to \a rgba, including its alpha. \sa rgba(), rgb() */ @@ -968,8 +966,7 @@ void QColor::setRgba(QRgb rgba) /*! \fn QRgb QColor::rgb() const - Returns the RGB value of the color. The alpha is stripped for - compatibility. + Returns the RGB value of the color. The alpha value is opaque. \sa getRgb(), rgba() */ @@ -983,7 +980,7 @@ QRgb QColor::rgb() const /*! \overload - Sets the RGB value to \a rgb, ignoring the alpha. + Sets the RGB value to \a rgb. The alpha value is set to opaque. */ void QColor::setRgb(QRgb rgb) { -- cgit v0.12 From fa41110be15ce458bd2b49bda03b147775d2ab01 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 22 Jan 2010 10:13:53 +0100 Subject: removed a debug trace --- src/corelib/animation/qabstractanimation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 2b4ab47..cedb43f 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -299,8 +299,6 @@ void QUnifiedTimer::registerRunningAnimation(QAbstractAnimation *animation) return; if (QAbstractAnimationPrivate::get(animation)->isPause) { - if (animation->duration() == -1) - qDebug() << "toto"; runningPauseAnimations << animation; } else runningLeafAnimations++; -- cgit v0.12 From ec44f83c4c7fa77e609a2458c4a5e26054fd5e85 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 22 Jan 2010 11:10:35 +0100 Subject: Fix rendering with simple shader in GL2 engine Need to bind the PMV matrix's attributes to their indexes in the simple shader, which is created in a seperate code path to all the other shaders. This should fix the qgl autotest failures. Reviewed-By: TrustMe --- src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 9fd9e18..8183f08 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -184,6 +184,9 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); + simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); simpleShaderProg->link(); if (!simpleShaderProg->isLinked()) { qCritical() << "Errors linking simple shader:" -- cgit v0.12 From 2ab883ca32df15f649b98120278707e078668c05 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 22 Jan 2010 12:39:18 +0100 Subject: Fix y-inverted pixmaps properly. There is a lot of code depending on that pixmaps are flipped upside down in the gl graphicssystem, so toggling this requires extensive testing. Since we're anyway questioning the relevance of this feature (compared to raster + GL viewport) its simply not worth the effort to fix it properly right now. Revert "Fixed y-inverted pixmaps on N900." This reverts commit 57473d5d2a7bd6ae3117f61ff29264a1b790bb01. --- src/opengl/qpixmapdata_gl.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 6d47687..aa80664 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -252,10 +252,6 @@ QGLPixmapData::QGLPixmapData(PixelType type) { setSerialNumber(++qt_gl_pixmap_serial); m_glDevice.setPixmapData(this); - - // Set InteralBindOptions minus the memory managed, since this - // QGLTexture is not managed as part of the internal texture cache - m_texture.options = QGLContext::PremultipliedAlphaBindOption; } QGLPixmapData::~QGLPixmapData() @@ -344,18 +340,18 @@ void QGLPixmapData::ensureCreated() const } if (!m_source.isNull()) { - glBindTexture(target, m_texture.id); if (external_format == GL_RGB) { - const QImage tx = m_source.convertToFormat(QImage::Format_RGB888); + const QImage tx = m_source.convertToFormat(QImage::Format_RGB888).mirrored(false, true); + + glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, GL_UNSIGNED_BYTE, tx.bits()); } else { const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format); + + glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, external_format, GL_UNSIGNED_BYTE, tx.bits()); - // convertToGLFormat will flip the Y axis, so it needs to - // be drawn upside down - m_texture.options |= QGLContext::InvertedYBindOption; } if (useFramebufferObjects()) -- cgit v0.12 From cbfe5019e135b85df37b3f38f79bef4dbe397cf6 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 22 Jan 2010 13:55:31 +0100 Subject: revert parts of 10392eef4fd4f9 We can't call QCOMPARE from within a nested function, because the return statement will just exit that function. VERIFY_COLOR can't be turned into a function this way. --- tests/auto/qwidget/tst_qwidget.cpp | 50 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index ee4e726..ea90ae3 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -5439,26 +5439,24 @@ public: QRegion r; }; -template -void verifyColor(R const& region, C const& color) -{ - const QRegion r = QRegion(region); - for (int i = 0; i < r.rects().size(); ++i) { - const QRect rect = r.rects().at(i); - for (int t = 0; t < 5; t++) { - const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), - rect.left(), rect.top(), - rect.width(), rect.height()); - QCOMPARE(pixmap.size(), rect.size()); - QPixmap expectedPixmap(pixmap); /* ensure equal formats */ - expectedPixmap.fill(color); - if (pixmap.toImage().pixel(0,0) != QColor(color).rgb() && t < 4 ) - { QTest::qWait(200); continue; } - QCOMPARE(pixmap.toImage().pixel(0,0), QColor(color).rgb()); - QCOMPARE(pixmap, expectedPixmap); - break; - } - } +#define VERIFY_COLOR(region, color) { \ + const QRegion r = QRegion(region); \ + for (int i = 0; i < r.rects().size(); ++i) { \ + const QRect rect = r.rects().at(i); \ + for (int t = 0; t < 5; t++) { \ + const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), \ + rect.left(), rect.top(), \ + rect.width(), rect.height()); \ + QCOMPARE(pixmap.size(), rect.size()); \ + QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \ + expectedPixmap.fill(color); \ + if (pixmap.toImage().pixel(0,0) != QColor(color).rgb() && t < 4 ) \ + { QTest::qWait(200); continue; } \ + QCOMPARE(pixmap.toImage().pixel(0,0), QColor(color).rgb()); \ + QCOMPARE(pixmap, expectedPixmap); \ + break; \ + } \ + } \ } void tst_QWidget::moveChild_data() @@ -5499,9 +5497,9 @@ void tst_QWidget::moveChild() #endif QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry()); QTRY_COMPARE(child.r, QRegion(child.rect())); - verifyColor(child.geometry().translated(tlwOffset), + VERIFY_COLOR(child.geometry().translated(tlwOffset), child.color); - verifyColor(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), + VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), parent.color); parent.reset(); child.reset(); @@ -5520,9 +5518,9 @@ void tst_QWidget::moveChild() // should be scrolled in backingstore QCOMPARE(child.r, QRegion()); #endif - verifyColor(child.geometry().translated(tlwOffset), + VERIFY_COLOR(child.geometry().translated(tlwOffset), child.color); - verifyColor(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), + VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), parent.color); } @@ -5553,8 +5551,8 @@ void tst_QWidget::showAndMoveChild() child.move(desktopDimensions.width()/2, desktopDimensions.height()/2); qApp->processEvents(); - verifyColor(child.geometry().translated(tlwOffset), Qt::blue); - verifyColor(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red); + VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue); + VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red); } void tst_QWidget::subtractOpaqueSiblings() -- cgit v0.12 From c8f4319b3a2ddacacd3bca67861a41e22dd1ada0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 22 Jan 2010 13:56:21 +0100 Subject: Re-added the Close button in QPrintPreviewDialog for Mac/Carbon. Modal Mac/Carbon dialogs do not have the close, minimize and resize window title buttons enabled, which makes it very hard to close modal dialogs. Task-number: QTBUG-7481 Reviewed-by: Kim --- src/gui/dialogs/qprintpreviewdialog.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp index 42be780..6723b53 100644 --- a/src/gui/dialogs/qprintpreviewdialog.cpp +++ b/src/gui/dialogs/qprintpreviewdialog.cpp @@ -207,6 +207,9 @@ public: QActionGroup *printerGroup; QAction *printAction; QAction *pageSetupAction; +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + QAction *closeAction; +#endif QPointer receiverToDisconnectOnClose; QByteArray memberToDisconnectOnClose; @@ -287,6 +290,9 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) toolbar->addSeparator(); toolbar->addAction(pageSetupAction); toolbar->addAction(printAction); +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + toolbar->addAction(closeAction); +#endif // Cannot use the actions' triggered signal here, since it doesn't autorepeat QToolButton *zoomInButton = static_cast(toolbar->widgetForAction(zoomInAction)); @@ -406,6 +412,10 @@ void QPrintPreviewDialogPrivate::setupActions() qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup")); QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print())); QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup())); +#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) + closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close")); + QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject())); +#endif // Initial state: fitPageAction->setChecked(true); -- cgit v0.12 From 6968a9b9281ef191c566a8e44447fc299cbdd4b7 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 22 Jan 2010 14:47:15 +0100 Subject: Fix QPainter::redirection() to pass autotest. Reviewed-by: Trond --- src/gui/painting/qpainter.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 1258d6b..cde6a2d 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7503,15 +7503,14 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset) { Q_ASSERT(device != 0); - if (*globalRedirectionAtomic() == 0) - return 0; - if (device->devType() == QInternal::Widget) { const QWidgetPrivate *widgetPrivate = static_cast(device)->d_func(); if (widgetPrivate->redirectDev) return widgetPrivate->redirected(offset); } + if (*globalRedirectionAtomic() == 0) + return 0; QMutexLocker locker(globalRedirectionsMutex()); QPaintDeviceRedirectionList *redirections = globalRedirections(); -- cgit v0.12 From 3e51b6c872e86a5e68a8e59770fc1bc32b84da0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 22 Jan 2010 12:46:32 +0100 Subject: QGraphicsWidget is painted twice on the inital show. Problem occured when doing something in the polishEvent() which eventually ended up as an update(). The problem was that in QGraphicsScene::addItem we scheduled a polish event after scheduling an update, resulting in update requests being processed before polish requests. Auto-test included. Task-number: QTBUG-6956 Reviewed-by: alexis --- src/gui/graphicsview/qgraphicsitem_p.h | 2 ++ src/gui/graphicsview/qgraphicsscene.cpp | 22 +++++++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 2 +- tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 25 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ac10aa7..bdd8863 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -178,6 +178,7 @@ public: sequentialOrdering(1), updateDueToGraphicsEffect(0), scenePosDescendants(0), + pendingPolish(0), globalStackingOrder(-1), q_ptr(0) { @@ -486,6 +487,7 @@ public: quint32 sequentialOrdering : 1; quint32 updateDueToGraphicsEffect : 1; quint32 scenePosDescendants : 1; + quint32 pendingPolish : 1; // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 088a6b9..7e182d0 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -429,12 +429,13 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::_q_polishItems() { - QSet::Iterator it = unpolishedItems.begin(); + QVector::Iterator it = unpolishedItems.begin(); const QVariant booleanTrueVariant(true); while (!unpolishedItems.isEmpty()) { QGraphicsItem *item = *it; it = unpolishedItems.erase(it); unpolishedItemsModified = false; + item->d_ptr->pendingPolish = false; if (!item->d_ptr->explicitlyHidden) { item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); @@ -638,8 +639,14 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) selectedItems.remove(item); hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); - unpolishedItems.remove(item); - unpolishedItemsModified = true; + if (item->d_ptr->pendingPolish) { + const int unpolishedIndex = unpolishedItems.indexOf(item); + if (unpolishedIndex != -1) { + unpolishedItems.remove(unpolishedIndex); + unpolishedItemsModified = true; + } + item->d_ptr->pendingPolish = false; + } resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays @@ -2501,6 +2508,11 @@ void QGraphicsScene::addItem(QGraphicsItem *item) return; } + if (d->unpolishedItems.isEmpty()) + QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); + d->unpolishedItems.append(item); + item->d_ptr->pendingPolish = true; + // Detach this item from its parent if the parent's scene is different // from this scene. if (QGraphicsItem *itemParent = item->d_ptr->parent) { @@ -2583,10 +2595,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) item->d_ptr->resolveFont(d->font.resolve()); item->d_ptr->resolvePalette(d->palette.resolve()); - if (d->unpolishedItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); - d->unpolishedItems.insert(item); - d->unpolishedItemsModified = true; // Reenable selectionChanged() for individual items --d->selectionChanging; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index d10811c..a3e36d0 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -108,7 +108,7 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QSet unpolishedItems; + QVector unpolishedItems; QList topLevelItems; bool needSortTopLevelItems; bool unpolishedItemsModified; diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 909ea54..d3132fe 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -163,6 +163,7 @@ private slots: void addChildInpolishEvent(); void polishEvent(); void polishEvent2(); + void initialShow(); // Task fixes void task236127_bspTreeIndexFails(); @@ -2856,6 +2857,30 @@ void tst_QGraphicsWidget::polishEvent2() QVERIFY(widget->events.contains(QEvent::Polish)); } +void tst_QGraphicsWidget::initialShow() +{ + class MyGraphicsWidget : public QGraphicsWidget + { public: + MyGraphicsWidget() : repaints(0) {} + int repaints; + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; } + void polishEvent() { update(); } + }; + + QGraphicsScene scene; + MyGraphicsWidget *widget = new MyGraphicsWidget; + + QGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + + QTest::qWait(100); + scene.addItem(widget); + QTest::qWait(100); + + QCOMPARE(widget->repaints, 1); +} + void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems() { QGraphicsScene scene; -- cgit v0.12 From 5f4af1b5b5a96875b42750a778dcf6695a844623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 22 Jan 2010 17:25:38 +0100 Subject: Potential crash when adding items from QGraphicsWidget::polishEvent(). These were processed immediately, so there was a fair chance that we could end up doing a virtual function call on items that were not fully constructed. This patch is also an optimization, since we never remove anything from the vector. Auto-test included. Reviewed-by: Jan-Arve --- src/gui/graphicsview/qgraphicsscene.cpp | 42 ++++++++++++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 1 - tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 43 ++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7e182d0..ae48bee 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -292,7 +292,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() processDirtyItemsEmitted(false), selectionChanging(0), needSortTopLevelItems(true), - unpolishedItemsModified(true), holesInTopLevelSiblingIndex(false), topLevelSequentialOrdering(true), scenePosDescendantsUpdatePending(false), @@ -429,23 +428,38 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::_q_polishItems() { - QVector::Iterator it = unpolishedItems.begin(); + if (unpolishedItems.isEmpty()) + return; + const QVariant booleanTrueVariant(true); - while (!unpolishedItems.isEmpty()) { - QGraphicsItem *item = *it; - it = unpolishedItems.erase(it); - unpolishedItemsModified = false; - item->d_ptr->pendingPolish = false; - if (!item->d_ptr->explicitlyHidden) { + QGraphicsItem *item = 0; + QGraphicsItemPrivate *itemd = 0; + const int oldUnpolishedCount = unpolishedItems.count(); + + for (int i = 0; i < oldUnpolishedCount; ++i) { + item = unpolishedItems.at(i); + if (!item) + continue; + itemd = item->d_ptr.data(); + itemd->pendingPolish = false; + if (!itemd->explicitlyHidden) { item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); } - if (item->isWidget()) { + if (itemd->isWidget) { QEvent event(QEvent::Polish); QApplication::sendEvent((QGraphicsWidget *)item, &event); } - if (unpolishedItemsModified) - it = unpolishedItems.begin(); + } + + if (unpolishedItems.count() == oldUnpolishedCount) { + // No new items were added to the vector. + unpolishedItems.clear(); + } else { + // New items were appended; keep them and remove the old ones. + unpolishedItems.remove(0, oldUnpolishedCount); + unpolishedItems.squeeze(); + QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection); } } @@ -641,10 +655,8 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) cachedItemsUnderMouse.removeAll(item); if (item->d_ptr->pendingPolish) { const int unpolishedIndex = unpolishedItems.indexOf(item); - if (unpolishedIndex != -1) { - unpolishedItems.remove(unpolishedIndex); - unpolishedItemsModified = true; - } + if (unpolishedIndex != -1) + unpolishedItems[unpolishedIndex] = 0; item->d_ptr->pendingPolish = false; } resetDirtyItem(item); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a3e36d0..54d8130 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -111,7 +111,6 @@ public: QVector unpolishedItems; QList topLevelItems; bool needSortTopLevelItems; - bool unpolishedItemsModified; bool holesInTopLevelSiblingIndex; bool topLevelSequentialOrdering; diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index c08a628e..547e7f5 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -270,6 +270,7 @@ private slots: void initialFocus_data(); void initialFocus(); void polishItems(); + void polishItems2(); void isActive(); void siblingIndexAlwaysValid(); @@ -3942,14 +3943,23 @@ void tst_QGraphicsScene::initialFocus() class PolishItem : public QGraphicsTextItem { public: - PolishItem(QGraphicsItem *parent = 0) : QGraphicsTextItem(parent) { } + PolishItem(QGraphicsItem *parent = 0) + : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { } + bool polished; + bool deleteChildrenInPolish; + bool addChildrenInPolish; protected: QVariant itemChange(GraphicsItemChange change, const QVariant& value) { if (change == ItemVisibleChange) { - if (value.toBool()) + polished = true; + if (deleteChildrenInPolish) qDeleteAll(childItems()); + if (addChildrenInPolish) { + for (int i = 0; i < 10; ++i) + new PolishItem(this); + } } return QGraphicsItem::itemChange(change, value); } @@ -3966,6 +3976,35 @@ void tst_QGraphicsScene::polishItems() QMetaObject::invokeMethod(&scene,"_q_polishItems"); } +void tst_QGraphicsScene::polishItems2() +{ + QGraphicsScene scene; + PolishItem *item = new PolishItem; + item->addChildrenInPolish = true; + item->deleteChildrenInPolish = true; + // These children should be deleted in the polish. + for (int i = 0; i < 20; ++i) + new PolishItem(item); + scene.addItem(item); + + // Wait for the polish event to be delivered. + QVERIFY(!item->polished); + QApplication::processEvents(); + QVERIFY(item->polished); + + // We deleted the children we added above, but we also + // added 10 new children. These should be polished in the next + // event loop iteration. + QList children = item->childItems(); + QCOMPARE(children.count(), 10); + foreach (QGraphicsItem *child, children) + QVERIFY(!static_cast(child)->polished); + + QApplication::processEvents(); + foreach (QGraphicsItem *child, children) + QVERIFY(static_cast(child)->polished); +} + void tst_QGraphicsScene::isActive() { QGraphicsScene scene1; -- cgit v0.12 From e5e6d9e7fe8f5c3baa5caf609198db1184f59ef9 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Fri, 22 Jan 2010 13:15:21 -0800 Subject: Implement QDirectFBPixmapData::scroll This is a very operation in DirectFB and saves a fair bit of overhead. Reviewed-by: Donald Carr --- .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 31 +++++++++++++++++++--- src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h | 1 + 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 1cbfdaf..f27440e 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -552,6 +552,34 @@ QImage *QDirectFBPixmapData::buffer() return &lockedImage; } + +bool QDirectFBPixmapData::scroll(int dx, int dy, const QRect &rect) +{ + if (!dfbSurface) { + return false; + } + unlockSurface(); + DFBResult result = dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + result = dfbSurface->SetPorterDuff(dfbSurface, DSPD_NONE); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + + const DFBRectangle source = { rect.x(), rect.y(), rect.width(), rect.height() }; + result = dfbSurface->Blit(dfbSurface, dfbSurface, &source, source.x + dx, source.y + dy); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::scroll", result); + return false; + } + + return true; +} + void QDirectFBPixmapData::invalidate() { if (dfbSurface) { @@ -568,6 +596,3 @@ void QDirectFBPixmapData::invalidate() QT_END_NAMESPACE #endif // QT_NO_QWS_DIRECTFB - - - diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index f9b14a9..da6edc6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -81,6 +81,7 @@ public: virtual QImage toImage() const; virtual QPaintEngine *paintEngine() const; virtual QImage *buffer(); + virtual bool scroll(int dx, int dy, const QRect &rect); // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice virtual int metric(QPaintDevice::PaintDeviceMetric m) const { return QDirectFBPaintDevice::metric(m); } -- cgit v0.12 From 517631a6021a480e4098e39e7d6f65d91c35559d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 22 Jan 2010 17:36:05 +0100 Subject: Another ASSERT while deleting spans That rare case when we are deleting the last span was not being taken care of. Unbelievable but true. Auto-test included. Reviewed-by: Thierry Reviewed-by: leo Task-number: QTBUG-6004 --- src/gui/itemviews/qtableview.cpp | 4 +++- tests/auto/qtableview/tst_qtableview.cpp | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 7eefb0b..3111896 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -114,7 +114,9 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height) } } else if (old_height > span->height()) { //remove the span from all the subspans lists that intersect the columns not covered anymore - Index::iterator it_y = index.lowerBound(qMin(-span->bottom(), 0)); + Index::iterator it_y = index.lowerBound(-span->bottom()); + if (it_y == index.end()) + it_y = index.find(-span->top()); // This is the only span remaining and we are deleting it. Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list while (-it_y.key() <= span->top() + old_height -1) { if (-it_y.key() > span->bottom()) { diff --git a/tests/auto/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp index 7a5e68f..430712c 100644 --- a/tests/auto/qtableview/tst_qtableview.cpp +++ b/tests/auto/qtableview/tst_qtableview.cpp @@ -3024,6 +3024,14 @@ void tst_QTableView::spans_data() << QPoint(0, 0) << 1 << 1; + + QTest::newRow("QTBUG-6004 (follow-up): No failing Q_ASSERT, then it passes.") + << 10 << 10 + << (SpanList() << QRect(2, 2, 1, 3) << QRect(2, 2, 1, 1)) + << false + << QPoint(0, 0) + << 1 + << 1; } void tst_QTableView::spans() -- cgit v0.12 From 6a3889146985e9e95b8a54e31003be8265e2469e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 15 Jan 2010 13:23:51 +0100 Subject: Small optimization in raster paint engine. Don't repeatedly update the pen / brush if no pen / brush is set. Reviewed-by: Gunnar Sletta --- src/gui/painting/qpaintengine_raster_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index b937f66..a1c73cc 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -264,13 +264,13 @@ private: #endif // Q_OS_SYMBIAN && QT_NO_FREETYPE inline void ensureBrush(const QBrush &brush) { - if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags) + if (!qbrush_fast_equals(state()->lastBrush, brush) || (brush.style() != Qt::NoBrush && state()->fillFlags)) updateBrush(brush); } inline void ensureBrush() { ensureBrush(state()->brush); } inline void ensurePen(const QPen &pen) { - if (!qpen_fast_equals(state()->lastPen, pen) || state()->strokeFlags) + if (!qpen_fast_equals(state()->lastPen, pen) || (pen.style() != Qt::NoPen && state()->strokeFlags)) updatePen(pen); } inline void ensurePen() { ensurePen(state()->pen); } -- cgit v0.12 From 235ea60ba2c8552038cf9ddc62d473ee865e2b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 19 Jan 2010 15:04:07 +0100 Subject: Made the trace replayer handle limited resolution cases better. Simply skip the updates that are outside the replay widget's bounds. Reviewed-by: Gunnar Sletta --- tools/qttracereplay/main.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp index 85e9b12..a932d72 100644 --- a/tools/qttracereplay/main.cpp +++ b/tools/qttracereplay/main.cpp @@ -52,6 +52,7 @@ public: ReplayWidget(const QString &filename); void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); public slots: void updateRect(); @@ -64,14 +65,15 @@ public: int currentIteration; QTime timer; + QList visibleUpdates; QList iterationTimes; QString filename; }; void ReplayWidget::updateRect() { - if (!updates.isEmpty()) - update(updates.at(currentFrame)); + if (!visibleUpdates.isEmpty()) + update(updates.at(visibleUpdates.at(currentFrame))); } void ReplayWidget::paintEvent(QPaintEvent *) @@ -80,10 +82,10 @@ void ReplayWidget::paintEvent(QPaintEvent *) // p.setClipRegion(frames.at(currentFrame).updateRegion); - buffer.draw(&p, currentFrame); + buffer.draw(&p, visibleUpdates.at(currentFrame)); ++currentFrame; - if (currentFrame >= buffer.numFrames()) { + if (currentFrame >= visibleUpdates.size()) { currentFrame = 0; ++currentIteration; @@ -119,7 +121,7 @@ void ReplayWidget::paintEvent(QPaintEvent *) if (iterationTimes.size() >= 10 || stddev < 4) { printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %d, stddev: %f %%, max(fps): %f\n", qPrintable(filename), - iterationTimes.size(), updates.size(), min, median, stddev, 1000. * updates.size() / min); + iterationTimes.size(), visibleUpdates.size(), min, median, stddev, 1000. * visibleUpdates.size() / min); deleteLater(); return; } @@ -130,6 +132,21 @@ void ReplayWidget::paintEvent(QPaintEvent *) QTimer::singleShot(0, this, SLOT(updateRect())); } +void ReplayWidget::resizeEvent(QResizeEvent *event) +{ + visibleUpdates.clear(); + + QRect bounds = rect(); + for (int i = 0; i < updates.size(); ++i) { + if (updates.at(i).intersects(bounds)) + visibleUpdates << i; + } + + if (visibleUpdates.size() != updates.size()) + printf("Warning: skipped %d frames due to limited resolution\n", updates.size() - visibleUpdates.size()); + +} + ReplayWidget::ReplayWidget(const QString &filename_) : currentFrame(0) , currentIteration(0) @@ -138,7 +155,6 @@ ReplayWidget::ReplayWidget(const QString &filename_) setWindowTitle(filename); QFile file(filename); - QRect bounds; if (!file.open(QIODevice::ReadOnly)) { printf("Failed to load input file '%s'\n", qPrintable(filename_)); return; -- cgit v0.12 From e5be6baa698f4779b6af97175015856d146bc479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 14 Jan 2010 13:46:52 +0100 Subject: Fixed child items with graphics effects not inheriting opacity. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to invalidate the graphics source pixmap cache for both child items and parent items when changing the opacity of a graphics item. Reviewed-by: Bjørn Erik Nilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 23 +++++++++++++-- src/gui/graphicsview/qgraphicsitem_p.h | 6 +++- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 34 ++++++++++++++++++++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d43176b..b8d392d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2565,7 +2565,9 @@ void QGraphicsItem::setOpacity(qreal opacity) // Update. if (d_ptr->scene) { #ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateGraphicsEffectsRecursively(); + d_ptr->invalidateParentGraphicsEffectsRecursively(); + if (!(d_ptr->flags & ItemDoesntPropagateOpacityToChildren)) + d_ptr->invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::OpacityChanged); #endif //QT_NO_GRAPHICSEFFECT d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -5075,7 +5077,7 @@ int QGraphicsItemPrivate::depth() const \internal */ #ifndef QT_NO_GRAPHICSEFFECT -void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() +void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively() { QGraphicsItemPrivate *itemPrivate = this; do { @@ -5087,6 +5089,21 @@ void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() } } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); } + +void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason) +{ + for (int i = 0; i < children.size(); ++i) { + QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data(); + if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; + if (childPrivate->graphicsEffect) { + childPrivate->notifyInvalidated = 1; + static_cast(childPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); + } + + childPrivate->invalidateChildGraphicsEffectsRecursively(reason); + } +} #endif //QT_NO_GRAPHICSEFFECT /*! @@ -5331,7 +5348,7 @@ void QGraphicsItem::update(const QRectF &rect) // Make sure we notify effects about invalidated source. #ifndef QT_NO_GRAPHICSEFFECT - d_ptr->invalidateGraphicsEffectsRecursively(); + d_ptr->invalidateParentGraphicsEffectsRecursively(); #endif //QT_NO_GRAPHICSEFFECT if (CacheMode(d_ptr->cacheMode) != NoCache) { diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index bdd8863..ff6e8bd 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -225,7 +225,11 @@ public: bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; int depth() const; #ifndef QT_NO_GRAPHICSEFFECT - void invalidateGraphicsEffectsRecursively(); + enum InvalidateReason { + OpacityChanged + }; + void invalidateParentGraphicsEffectsRecursively(); + void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason); #endif //QT_NO_GRAPHICSEFFECT void invalidateDepthRecursively(); void resolveDepth(); diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index 51e2a57..795431b 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -71,6 +71,7 @@ private slots: void colorize(); void drawPixmapItem(); void deviceCoordinateTranslateCaching(); + void inheritOpacity(); }; void tst_QGraphicsEffect::initTestCase() @@ -79,8 +80,8 @@ void tst_QGraphicsEffect::initTestCase() class CustomItem : public QGraphicsRectItem { public: - CustomItem(qreal x, qreal y, qreal width, qreal height) - : QGraphicsRectItem(x, y, width, height), numRepaints(0), + CustomItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem *parent = 0) + : QGraphicsRectItem(x, y, width, height, parent), numRepaints(0), m_painter(0), m_styleOption(0) {} @@ -560,6 +561,35 @@ void tst_QGraphicsEffect::deviceCoordinateTranslateCaching() QVERIFY(item->numRepaints == numRepaints); } +void tst_QGraphicsEffect::inheritOpacity() +{ + QGraphicsScene scene; + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 10, 10); + CustomItem *item = new CustomItem(0, 0, 10, 10, rectItem); + + scene.addItem(rectItem); + + item->setGraphicsEffect(new DeviceEffect); + item->setPen(Qt::NoPen); + item->setBrush(Qt::red); + + rectItem->setOpacity(0.5); + + QGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + + QTRY_VERIFY(item->numRepaints >= 1); + + int numRepaints = item->numRepaints; + + rectItem->setOpacity(1); + QTest::qWait(50); + + // item should have been rerendered due to opacity changing + QTRY_VERIFY(item->numRepaints > numRepaints); +} + QTEST_MAIN(tst_QGraphicsEffect) #include "tst_qgraphicseffect.moc" -- cgit v0.12 From a85f708449a5fb61740ec12abd4cb9df3a5265ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 25 Jan 2010 11:52:14 +0100 Subject: Added optimization flag to QGraphicsItemPrivate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid traversing the whole child hierarchy when opacity changes unless there are children with graphics effects. Reviewed-by: Bjørn Erik Nilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 22 ++++++++++++++++++++++ src/gui/graphicsview/qgraphicsitem_p.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b8d392d..66493b7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1075,6 +1075,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q p = p->d_ptr->parent; } + // Update graphics effect optimization flag + if (newParent && (graphicsEffect || mayHaveChildWithGraphicsEffect)) + newParent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); + // Update focus scope item ptr in new scope. QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; if (newFocusScopeItem && newParent) { @@ -2612,6 +2616,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) if (d_ptr->graphicsEffect) { delete d_ptr->graphicsEffect; d_ptr->graphicsEffect = 0; + } else if (d_ptr->parent) { + d_ptr->parent->d_ptr->updateChildWithGraphicsEffectFlagRecursively(); } if (effect) { @@ -2625,6 +2631,19 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect) } #endif //QT_NO_GRAPHICSEFFECT +void QGraphicsItemPrivate::updateChildWithGraphicsEffectFlagRecursively() +{ +#ifndef QT_NO_GRAPHICSEFFECT + QGraphicsItemPrivate *itemPrivate = this; + do { + // parent chain already notified? + if (itemPrivate->mayHaveChildWithGraphicsEffect) + return; + itemPrivate->mayHaveChildWithGraphicsEffect = 1; + } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); +#endif +} + /*! \internal \since 4.6 @@ -5092,6 +5111,9 @@ void QGraphicsItemPrivate::invalidateParentGraphicsEffectsRecursively() void QGraphicsItemPrivate::invalidateChildGraphicsEffectsRecursively(QGraphicsItemPrivate::InvalidateReason reason) { + if (!mayHaveChildWithGraphicsEffect) + return; + for (int i = 0; i < children.size(); ++i) { QGraphicsItemPrivate *childPrivate = children.at(i)->d_ptr.data(); if (reason == OpacityChanged && (childPrivate->flags & QGraphicsItem::ItemIgnoresParentOpacity)) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ff6e8bd..986a977 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -179,6 +179,7 @@ public: updateDueToGraphicsEffect(0), scenePosDescendants(0), pendingPolish(0), + mayHaveChildWithGraphicsEffect(0), globalStackingOrder(-1), q_ptr(0) { @@ -196,6 +197,7 @@ public: return item->d_ptr.data(); } + void updateChildWithGraphicsEffectFlagRecursively(); void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); void updateAncestorFlags(); @@ -492,6 +494,7 @@ public: quint32 updateDueToGraphicsEffect : 1; quint32 scenePosDescendants : 1; quint32 pendingPolish : 1; + quint32 mayHaveChildWithGraphicsEffect : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From 8ef52111099e1a588d872305d07f0f9e514fe2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Mon, 25 Jan 2010 17:30:26 +0100 Subject: Updated docs regarding QGLWidget::renderText() limitations. Reviewed-by: Trust Me --- src/opengl/qgl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 3f32cf3..48e43b2 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4393,6 +4393,13 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str, \note This function temporarily disables depth-testing when the text is drawn. + \note This function can only be used inside a + QPainter::beginNativePainting()/QPainter::endNativePainting() block + if the default OpenGL paint engine is QPaintEngine::OpenGL. To make + QPaintEngine::OpenGL the default GL engine, call + QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the + QApplication constructor. + \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead. */ -- cgit v0.12 From 0a3ce6fa04ed2b085fe72b89d302a3a5f9e82948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Tue, 26 Jan 2010 10:55:31 +0100 Subject: Fixed an infinite loop that could occur when reading invalid BMP images. Task-number: QTBUG-7530 Reviewed-by: Kim --- src/gui/image/qbmphandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 854be2e..42e19b8 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -144,7 +144,7 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi) static int calc_shift(int mask) { int result = 0; - while (!(mask & 1)) { + while (mask && !(mask & 1)) { result++; mask >>= 1; } -- cgit v0.12 From 5ccd8ceb06a9be29f773d170d5dd8c67a8d6c86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 26 Jan 2010 14:14:47 +0100 Subject: Stabilize tst_QGraphicsScene::polishItems2 (new test) We are only interested in getting the posted MetaCall events delivered, so we can get away with sendPostedEvents() instead of processEvents(). Makes the test also pass on Mac g++ carbon 32. --- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 547e7f5..6743fbe 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -3989,7 +3989,7 @@ void tst_QGraphicsScene::polishItems2() // Wait for the polish event to be delivered. QVERIFY(!item->polished); - QApplication::processEvents(); + QApplication::sendPostedEvents(&scene, QEvent::MetaCall); QVERIFY(item->polished); // We deleted the children we added above, but we also @@ -4000,7 +4000,7 @@ void tst_QGraphicsScene::polishItems2() foreach (QGraphicsItem *child, children) QVERIFY(!static_cast(child)->polished); - QApplication::processEvents(); + QApplication::sendPostedEvents(&scene, QEvent::MetaCall); foreach (QGraphicsItem *child, children) QVERIFY(static_cast(child)->polished); } -- cgit v0.12 From 5241ca84e0884e9d0814094eb6949ae27b19c6f9 Mon Sep 17 00:00:00 2001 From: Leonardo Sobral Cunha Date: Fri, 8 Jan 2010 16:31:01 +0100 Subject: Fixes visibility update missing when doing setParentItem on graphicsitem Calling setParentItem is causing the previous opacity/visible updates to be discarded because the dirty flags were not propagated to the new parent. Also removed some unnecessary 'markDirty' and 'update' calls. Task-number: QTBUG-6738 Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 30 ++------- src/gui/graphicsview/qgraphicsitem_p.h | 33 ++++++++++ src/gui/graphicsview/qgraphicsscene.cpp | 14 +---- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 86 ++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 36 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 66493b7..dc20faf 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1113,11 +1113,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q } if ((parent = newParent)) { - bool implicitUpdate = false; if (parent->d_func()->scene && parent->d_func()->scene != scene) { // Move this item to its new parent's scene parent->d_func()->scene->addItem(q); - implicitUpdate = true; } else if (!parent->d_func()->scene && scene) { // Remove this item from its former scene scene->removeItem(q); @@ -1127,25 +1125,25 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q if (thisPointerVariant) parent->itemChange(QGraphicsItem::ItemChildAddedChange, *thisPointerVariant); if (scene) { - if (!implicitUpdate) - scene->d_func()->markDirty(q_ptr); - // Re-enable scene pos notifications for new ancestors if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges)) scene->d_func()->setScenePosItemEnabled(q, true); } + // Propagate dirty flags to the new parent + markParentDirty(/*updateBoundingRect=*/true); + // Inherit ancestor flags from the new parent. updateAncestorFlags(); // Update item visible / enabled. if (parent->d_ptr->visible != visible) { if (!parent->d_ptr->visible || !explicitlyHidden) - setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ !implicitUpdate); + setVisibleHelper(parent->d_ptr->visible, /* explicit = */ false, /* update = */ false); } if (parent->isEnabled() != enabled) { if (!parent->d_ptr->enabled || !explicitlyDisabled) - setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ !implicitUpdate); + setEnabledHelper(parent->d_ptr->enabled, /* explicit = */ false, /* update = */ false); } // Auto-activate if visible and the parent is active. @@ -1161,10 +1159,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q setVisibleHelper(true, /* explicit = */ false); if (!enabled && !explicitlyDisabled) setEnabledHelper(true, /* explicit = */ false); - - // If the item is being deleted, the whole scene will be updated. - if (scene) - scene->d_func()->markDirty(q_ptr); } } @@ -7263,19 +7257,7 @@ void QGraphicsItem::prepareGeometryChange() } } - QGraphicsItem *parent = this; - while ((parent = parent->d_ptr->parent)) { - QGraphicsItemPrivate *parentp = parent->d_ptr.data(); - parentp->dirtyChildrenBoundingRect = 1; - // ### Only do this if the parent's effect applies to the entire subtree. - parentp->notifyBoundingRectChanged = 1; -#ifndef QT_NO_GRAPHICSEFFECT - if (parentp->scene && parentp->graphicsEffect) { - parentp->notifyInvalidated = 1; - static_cast(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache(); - } -#endif - } + d_ptr->markParentDirty(/*updateBoundingRect=*/true); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 986a977..5ad6cd5 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -406,6 +406,8 @@ public: return !visible || (childrenCombineOpacity() && isFullyTransparent()); } + inline void markParentDirty(bool updateBoundingRect = false); + void setFocusHelper(Qt::FocusReason focusReason, bool climb); void setSubFocus(QGraphicsItem *rootItem = 0); void clearSubFocus(QGraphicsItem *rootItem = 0); @@ -754,6 +756,37 @@ inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; } +/*! + \internal +*/ +inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect) +{ + QGraphicsItemPrivate *parentp = this; + while (parentp->parent) { + parentp = parentp->parent->d_ptr.data(); + parentp->dirtyChildren = 1; + + if (updateBoundingRect) { + parentp->dirtyChildrenBoundingRect = 1; + // ### Only do this if the parent's effect applies to the entire subtree. + parentp->notifyBoundingRectChanged = 1; + } +#ifndef QT_NO_GRAPHICSEFFECT + if (parentp->graphicsEffect) { + if (updateBoundingRect) { + parentp->notifyInvalidated = 1; + static_cast(parentp->graphicsEffect->d_func() + ->source->d_func())->invalidateCache(); + } + if (parentp->graphicsEffect->isEnabled()) { + parentp->dirty = 1; + parentp->fullUpdatePending = 1; + } + } +#endif + } +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ae48bee..9219773 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1955,7 +1955,7 @@ QList QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe \since 4.3 This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). - + This function is deprecated and returns incorrect results if the scene contains items that ignore transformations. Use the overload that takes a QTransform instead. @@ -4903,17 +4903,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (ignoreOpacity) item->d_ptr->ignoreOpacity = 1; - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - p->d_ptr->dirtyChildren = 1; -#ifndef QT_NO_GRAPHICSEFFECT - if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { - p->d_ptr->dirty = 1; - p->d_ptr->fullUpdatePending = 1; - } -#endif //QT_NO_GRAPHICSEFFECT - p = p->d_ptr->parent; - } + item->d_ptr->markParentDirty(); } static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 8e43bce..14b9ef0 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -316,6 +316,7 @@ private slots: void childrenBoundingRectTransformed(); void childrenBoundingRect2(); void childrenBoundingRect3(); + void childrenBoundingRect4(); void group(); void setGroup(); void setGroup2(); @@ -417,6 +418,7 @@ private slots: void task197802_childrenVisibility(); void QTBUG_4233_updateCachedWithSceneRect(); void QTBUG_5418_textItemSetDefaultColor(); + void QTBUG_6738_missingUpdateWithSetParent(); private: QList paintedItems; @@ -3257,6 +3259,32 @@ void tst_QGraphicsItem::childrenBoundingRect3() QCOMPARE(subTreeRect.height(), qreal(251.7766952966369)); } +void tst_QGraphicsItem::childrenBoundingRect4() +{ + QGraphicsScene scene; + + QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10)); + QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20)); + QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30)); + rect2->setParentItem(rect); + rect3->setParentItem(rect); + + QGraphicsView view(&scene); + view.show(); + + QTest::qWaitForWindowShown(&view); + + // Try to mess up the cached bounding rect. + rect->childrenBoundingRect(); + rect2->childrenBoundingRect(); + + rect3->setOpacity(0.0); + rect3->setParentItem(rect2); + + QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect()); + QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect()); +} + void tst_QGraphicsItem::group() { QGraphicsScene scene; @@ -9869,5 +9897,63 @@ void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242) } +void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent() +{ + // In all 3 test cases below the reparented item should disappear + EventTester *parent = new EventTester; + EventTester *child = new EventTester(parent); + EventTester *child2 = new EventTester(parent); + EventTester *child3 = new EventTester(parent); + EventTester *child4 = new EventTester(parent); + + child->setPos(10, 10); + child2->setPos(20, 20); + child3->setPos(30, 30); + child4->setPos(40, 40); + + QGraphicsScene scene; + scene.addItem(parent); + + class MyGraphicsView : public QGraphicsView + { public: + int repaints; + QRegion paintedRegion; + MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {} + void paintEvent(QPaintEvent *e) + { + ++repaints; + paintedRegion += e->region(); + QGraphicsView::paintEvent(e); + } + void reset() { repaints = 0; paintedRegion = QRegion(); } + }; + + MyGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + QTRY_VERIFY(view.repaints > 0); + + // test case #1 + view.reset(); + child2->setVisible(false); + child2->setParentItem(child); + + QTRY_VERIFY(view.repaints == 1); + + // test case #2 + view.reset(); + child3->setOpacity(0.0); + child3->setParentItem(child); + + QTRY_VERIFY(view.repaints == 1); + + // test case #3 + view.reset(); + child4->setParentItem(child); + child4->setVisible(false); + + QTRY_VERIFY(view.repaints == 1); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 416cf8a5a9384f942282a2c715ec4832eeba001d Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 27 Jan 2010 09:34:39 +1000 Subject: Compile with no-webkit - add missing semi-colons. Reviewed-by: Sarah Smith --- tools/assistant/tools/assistant/centralwidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index c8f41e4..055fa1c 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -1088,7 +1088,7 @@ CentralWidget::setSourceFromSearch(const QUrl &url) { setSource(url); #if defined(QT_NO_WEBKIT) - highlightSearchTerms() + highlightSearchTerms(); #else connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, SLOT(highlightSearchTerms())); @@ -1100,7 +1100,7 @@ CentralWidget::setSourceFromSearchInNewTab(const QUrl &url) { setSourceInNewTab(url); #if defined(QT_NO_WEBKIT) - highlightSearchTerms() + highlightSearchTerms(); #else connect(currentHelpViewer(), SIGNAL(loadFinished(bool)), this, SLOT(highlightSearchTerms())); -- cgit v0.12 From be0807cf52a11f0bc4dc5b06c9a91bc2980667d3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 27 Jan 2010 10:41:48 +0100 Subject: Designer: Add lower/raise to context menu. Task-number: QTCREATORBUG-592 --- tools/designer/src/components/formeditor/formwindow.cpp | 5 +++++ tools/designer/src/components/formeditor/formwindow.h | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp index 2d013c9..9fd084d 100644 --- a/tools/designer/src/components/formeditor/formwindow.cpp +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -2219,6 +2219,11 @@ QMenu *FormWindow::createPopupMenu(QWidget *w) QToolBoxHelper::addToolBoxContextMenuActions(toolBox, popup); } + if (manager->actionLower()->isEnabled()) { + popup->addAction(manager->actionLower()); + popup->addAction(manager->actionRaise()); + popup->addSeparator(); + } popup->addAction(manager->actionCut()); popup->addAction(manager->actionCopy()); } diff --git a/tools/designer/src/components/formeditor/formwindow.h b/tools/designer/src/components/formeditor/formwindow.h index eed7417..3eee476 100644 --- a/tools/designer/src/components/formeditor/formwindow.h +++ b/tools/designer/src/components/formeditor/formwindow.h @@ -278,8 +278,6 @@ private: void checkPreviewGeometry(QRect &r); - void finishContextMenu(QWidget *w, QWidget *menuParent, QContextMenuEvent *e); - bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e); bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); -- cgit v0.12 From 878bf8b1dde10e28d9acd91002fd7b4e2a7a64e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 27 Jan 2010 11:58:34 +0100 Subject: Compiler warning. --- src/gui/effects/qgraphicseffect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index ad23df3..10ef5ea 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -383,9 +383,9 @@ void QGraphicsEffectSourcePrivate::invalidateCache(InvalidateReason reason) cons { if (m_cachedMode != QGraphicsEffect::PadToEffectiveBoundingRect && (reason == EffectRectChanged - || reason == TransformChanged - && m_cachedSystem == Qt::LogicalCoordinates)) + || (reason == TransformChanged && m_cachedSystem == Qt::LogicalCoordinates))) { return; + } QPixmapCache::remove(m_cacheKey); } -- cgit v0.12 From 15f690e6890caae8d0c000bcc34103b1841307eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Wed, 27 Jan 2010 12:46:23 +0100 Subject: Added a warning to QGLWidget::renderText(). renderText() can't be used while a GL 2 paint engine is active on the same device, because it will clash with the GL 1 engine and wreck havoc. We simply don't support that scenario. Task-number: QTBUG-7592 Reviewed-by: Samuel --- src/opengl/qgl.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 48e43b2..2a60708 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4419,8 +4419,17 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, bool auto_swap = autoBufferSwap(); QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); - qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); + QPaintEngine *engine = paintEngine(); + if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { + qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" + " active on the same device is not allowed."); + return; + } + + // this changes what paintEngine() returns + qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); + engine = paintEngine(); QPainter *p; bool reuse_painter = false; if (engine->isActive()) { @@ -4513,8 +4522,17 @@ void QGLWidget::renderText(double x, double y, double z, const QString &str, con win_y = height - win_y; // y is inverted QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine(); - qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); QPaintEngine *engine = paintEngine(); + + if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) { + qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is" + " active on the same device is not allowed."); + return; + } + + // this changes what paintEngine() returns + qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL); + engine = paintEngine(); QPainter *p; bool reuse_painter = false; bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST); -- cgit v0.12 From c64635b53a014da36203c576954042916cf87a7c Mon Sep 17 00:00:00 2001 From: Leonardo Sobral Cunha Date: Wed, 27 Jan 2010 12:09:17 +0100 Subject: Avoid call markParentDirty twice in prepareGeometryChange Reviewed-by: bnilsen --- src/gui/graphicsview/qgraphicsitem.cpp | 4 +++- src/gui/graphicsview/qgraphicsscene.cpp | 6 ++++-- src/gui/graphicsview/qgraphicsscene_p.h | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index dc20faf..561bd42 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7240,7 +7240,9 @@ void QGraphicsItem::prepareGeometryChange() QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); scenePrivate->index->prepareBoundingRectChange(this); - scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true); + scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false, + /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false, + /*updateBoundingRect=*/true); // For compatibility reasons, we have to update the item's old geometry // if someone is connected to the changed signal or the scene has no views. diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9219773..54d47fa 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4832,7 +4832,8 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q } void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, - bool force, bool ignoreOpacity, bool removingItemFromScene) + bool force, bool ignoreOpacity, bool removingItemFromScene, + bool updateBoundingRect) { Q_ASSERT(item); if (updateAll) @@ -4903,7 +4904,8 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (ignoreOpacity) item->d_ptr->ignoreOpacity = 1; - item->d_ptr->markParentDirty(); + if (!updateBoundingRect) + item->d_ptr->markParentDirty(); } static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 54d8130..04ffe0f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -222,7 +222,8 @@ public: QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, - bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false); + bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false, + bool updateBoundingRect = false); void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, qreal parentOpacity = qreal(1.0)); -- cgit v0.12 From f3604bd0abc1ca0768c565e7753ce8e2fda0f2ba Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 28 Jan 2010 11:39:02 +1000 Subject: Add additional text and painting benchmarks. These benchmarks have been moved in from the kinetic-declarativeui branch as they are not QML specific. --- tests/benchmarks/qpainter/tst_qpainter.cpp | 503 +++++++++++++++++++++++++++++ tests/benchmarks/qtext/main.cpp | 205 ++++++++++++ 2 files changed, 708 insertions(+) diff --git a/tests/benchmarks/qpainter/tst_qpainter.cpp b/tests/benchmarks/qpainter/tst_qpainter.cpp index 7c6634e..39b2244 100644 --- a/tests/benchmarks/qpainter/tst_qpainter.cpp +++ b/tests/benchmarks/qpainter/tst_qpainter.cpp @@ -45,6 +45,10 @@ #include #include #include +#include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif Q_DECLARE_METATYPE(QLine) Q_DECLARE_METATYPE(QRect) @@ -178,6 +182,35 @@ private slots: void clipAndFill_data(); void clipAndFill(); + void drawRoundedRect(); + void drawScaledRoundedRect(); + void drawTransformedRoundedRect(); + + void drawScaledAntialiasedRoundedRect_data(); + void drawTransformedAntialiasedRoundedRect_data(); + void drawAntialiasedRoundedRect(); + void drawScaledAntialiasedRoundedRect(); + void drawTransformedAntialiasedRoundedRect(); + + void drawScaledImageRoundedRect_data(); + void drawTransformedImageRoundedRect_data(); + void drawImageRoundedRect(); + void drawScaledImageRoundedRect(); + void drawTransformedImageRoundedRect(); + + void drawScaledBorderPixmapRoundedRect_data(); + void drawTransformedBorderPixmapRoundedRect_data(); + void drawBorderPixmapRoundedRect(); + void drawScaledBorderPixmapRoundedRect(); + void drawTransformedBorderPixmapRoundedRect(); + + void drawTransformedTransparentImage_data(); + void drawTransformedSemiTransparentImage_data(); + void drawTransformedFilledImage_data(); + void drawTransformedTransparentImage(); + void drawTransformedSemiTransparentImage(); + void drawTransformedFilledImage(); + private: void setupBrushes(); void createPrimitives(); @@ -185,6 +218,8 @@ private: void drawPrimitives_data_helper(bool fancypens); void fillPrimitives_helper(QPainter *painter, PrimitiveType type, PrimitiveSet *s); + QTransform transformForAngle(qreal angle); + QPaintDevice *surface() { return new QPixmap(1024, 1024); @@ -1123,6 +1158,474 @@ void tst_QPainter::clipAndFill() } } +QTransform tst_QPainter::transformForAngle(qreal angle) +{ + const qreal inv_dist_to_plane = 1. / 1024.; + + QTransform transform; + + QTransform rotTrans; + rotTrans.translate(-40, 0); + QTransform rotTrans2; + rotTrans2.translate(40, 0); + + qreal rad = angle * 2. * M_PI / 360.; + qreal c = ::cos(rad); + qreal s = ::sin(rad); + + qreal x = 0; + qreal y = 80; + qreal z = 0; + + qreal len = x * x + y * y + z * z; + if (len != 1.) { + len = ::sqrt(len); + x /= len; + y /= len; + z /= len; + } + + QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane, + y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane, + 0, 0, 1); + + transform *= rotTrans; + transform *= rot; + transform *= rotTrans2; + + return transform; +} + +void tst_QPainter::drawRoundedRect() +{ + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); + } +} + +void tst_QPainter::drawScaledRoundedRect() +{ + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + p.scale(3, 3); + + QBENCHMARK { + p.drawRoundedRect(10, 10, 80, 80, 10, 10); + } +} + +void tst_QPainter::drawTransformedRoundedRect() +{ + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawRoundedRect(100, 100, 80, 80, 10, 10); + } +} + +void tst_QPainter::drawAntialiasedRoundedRect() +{ + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); + } +} + +void tst_QPainter::drawScaledAntialiasedRoundedRect_data() +{ + QTest::addColumn("scale"); + + for (float i = 0; i < 3; i += .1) + QTest::newRow(QString(QLatin1String("scale=%1")).arg(i).toLatin1()) << i; +} + +void tst_QPainter::drawScaledAntialiasedRoundedRect() +{ + QFETCH(float, scale); + + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + p.scale(scale, scale); + + QBENCHMARK { + p.drawRoundedRect(10, 10, 80, 80, 10, 10); + } +} + +void tst_QPainter::drawTransformedAntialiasedRoundedRect_data() +{ + QTest::addColumn("transform"); + + for (float angle = 0; angle < 360; angle += 10) + QTest::newRow(QString(QLatin1String("angle=%1")).arg(angle).toLatin1()) << transformForAngle(angle); +} + +void tst_QPainter::drawTransformedAntialiasedRoundedRect() +{ + QFETCH(QTransform, transform); + + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.setWorldTransform(transform); + p.drawRoundedRect(100, 100, 80, 80, 10, 10); + } +} + +void tst_QPainter::drawImageRoundedRect() +{ + //setup image + const int radius = 10; + QImage rectImage(81, 81, QImage::Format_ARGB32_Premultiplied); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.drawImage(0,0, rectImage); + } +} + +void tst_QPainter::drawScaledImageRoundedRect_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QPainter::drawScaledImageRoundedRect() +{ + QFETCH(int, imageType); + + //setup image + const int radius = 10; + QImage rectImage(81, 81, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + p.scale(3, 3); + + QBENCHMARK { + p.drawImage(0,0, rectImage); + } +} + +void tst_QPainter::drawTransformedImageRoundedRect_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QPainter::drawTransformedImageRoundedRect() +{ + QFETCH(int, imageType); + + //setup image + const int radius = 10; + QImage rectImage(81, 81, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(100,100, rectImage); + } +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QPainter::drawBorderPixmapRoundedRect() +{ + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, QImage::Format_ARGB32_Premultiplied); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + const int pw = 2; + int width = 80; + int height = 80; + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } +} + +void tst_QPainter::drawScaledBorderPixmapRoundedRect_data() +{ + QTest::addColumn("scale"); + QTest::addColumn("imageType"); + + for (float i = 0; i < 3; i += .1) + QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB32_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB32_Premultiplied; + //for (float i = 0; i < 3; i += .1) + // QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB8565_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB8565_Premultiplied; +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QPainter::drawScaledBorderPixmapRoundedRect() +{ + QFETCH(float, scale); + QFETCH(int, imageType); + + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + p.scale(scale, scale); + + QBENCHMARK { + const int pw = 2; + int width = 80; + int height = 80; + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } +} + +void tst_QPainter::drawTransformedBorderPixmapRoundedRect_data() +{ + QTest::addColumn("transform"); + QTest::addColumn("imageType"); + + for (float angle = 0; angle < 360; angle += 10) + QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB32_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB32_Premultiplied; + //for (float angle = 0; angle < 360; angle += 10) + // QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB8565_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB8565_Premultiplied; + +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QPainter::drawTransformedBorderPixmapRoundedRect() +{ + QFETCH(QTransform, transform); + QFETCH(int, imageType); + + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(transform); + const int pw = 2; + int width = 80; + int height = 80; + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } +} + +void tst_QPainter::drawTransformedTransparentImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QPainter::drawTransformedTransparentImage() +{ + QFETCH(int, imageType); + + //setup image + QImage transImage(200, 200, (QImage::Format)imageType); + transImage.fill(0); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, transImage); + } +} + +void tst_QPainter::drawTransformedSemiTransparentImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QPainter::drawTransformedSemiTransparentImage() +{ + QFETCH(int, imageType); + + //setup image + QImage transImage(200, 200, (QImage::Format)imageType); + transImage.fill(QColor(0,0,0, 128).rgba()); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, transImage); + } +} + +void tst_QPainter::drawTransformedFilledImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QPainter::drawTransformedFilledImage() +{ + QFETCH(int, imageType); + + //setup image + QImage filledImage(200, 200, (QImage::Format)imageType); + filledImage.fill(QColor(0,0,0).rgb()); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, filledImage); + } +} QTEST_MAIN(tst_QPainter) diff --git a/tests/benchmarks/qtext/main.cpp b/tests/benchmarks/qtext/main.cpp index 4bd2bee..9854a9f 100644 --- a/tests/benchmarks/qtext/main.cpp +++ b/tests/benchmarks/qtext/main.cpp @@ -44,7 +44,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -56,6 +59,7 @@ class tst_QText: public QObject public: tst_QText() { m_lorem = QString::fromLatin1("Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi."); + m_shortLorem = QString::fromLatin1("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); } private slots: @@ -69,8 +73,26 @@ private slots: void odfWriting_text(); void odfWriting_images(); + void constructControl(); + void constructDocument(); + + void layout(); + void paintLayoutToPixmap(); + void paintLayoutToPixmap_painterFill(); + + void document(); + void paintDocToPixmap(); + void paintDocToPixmap_painterFill(); + + void control(); + void paintControlToPixmap(); + void paintControlToPixmap_painterFill(); + private: + QSize setupTextLayout(QTextLayout *layout); + QString m_lorem; + QString m_shortLorem; }; void tst_QText::loadHtml_data() @@ -195,6 +217,189 @@ void tst_QText::odfWriting_images() delete doc; } +QSize tst_QText::setupTextLayout(QTextLayout *layout) +{ + bool wrap = true; + int wrapWidth = 300; + layout->setCacheEnabled(true); + + int height = 0; + qreal widthUsed = 0; + qreal lineWidth = 0; + + //set manual width + if (wrap) + lineWidth = wrapWidth; + + layout->beginLayout(); + + while (1) { + QTextLine line = layout->createLine(); + if (!line.isValid()) + break; + + if (wrap) + line.setLineWidth(lineWidth); + } + layout->endLayout(); + + for (int i = 0; i < layout->lineCount(); ++i) { + QTextLine line = layout->lineAt(i); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + line.setPosition(QPointF(0, height)); + height += int(line.height()); + } + return QSize(qCeil(widthUsed), height); +} + +void tst_QText::constructControl() +{ + QTextControl *control = new QTextControl; + delete control; + + QBENCHMARK { + QTextControl *control = new QTextControl; + delete control; + } +} + +void tst_QText::constructDocument() +{ + QTextDocument *doc = new QTextDocument; + delete doc; + + QBENCHMARK { + QTextDocument *doc = new QTextDocument; + delete doc; + } +} + +void tst_QText::layout() +{ + QTextLayout layout(m_shortLorem); + setupTextLayout(&layout); + + QBENCHMARK { + QTextLayout layout(m_shortLorem); + setupTextLayout(&layout); + } +} + +void tst_QText::paintLayoutToPixmap() +{ + QTextLayout layout(m_shortLorem); + QSize size = setupTextLayout(&layout); + + QBENCHMARK { + QPixmap img(size); + img.fill(Qt::transparent); + QPainter p(&img); + layout.draw(&p, QPointF(0, 0)); + } +} + +void tst_QText::paintLayoutToPixmap_painterFill() +{ + QTextLayout layout(m_shortLorem); + QSize size = setupTextLayout(&layout); + + QBENCHMARK { + QPixmap img(size); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, img.width(), img.height(), Qt::transparent); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + layout.draw(&p, QPointF(0, 0)); + } +} + +void tst_QText::document() +{ + QTextDocument *doc = new QTextDocument; + + QBENCHMARK { + QTextDocument *doc = new QTextDocument; + doc->setHtml(m_shortLorem); + } +} + +void tst_QText::paintDocToPixmap() +{ + QTextDocument *doc = new QTextDocument; + doc->setHtml(m_shortLorem); + doc->setTextWidth(300); + QSize size = doc->size().toSize(); + + QBENCHMARK { + QPixmap img(size); + img.fill(Qt::transparent); + QPainter p(&img); + doc->drawContents(&p); + } +} + +void tst_QText::paintDocToPixmap_painterFill() +{ + QTextDocument *doc = new QTextDocument; + doc->setHtml(m_shortLorem); + doc->setTextWidth(300); + QSize size = doc->size().toSize(); + + QBENCHMARK { + QPixmap img(size); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, img.width(), img.height(), Qt::transparent); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + doc->drawContents(&p); + } +} + +void tst_QText::control() +{ + QTextControl *control = new QTextControl(m_shortLorem); + + QBENCHMARK { + QTextControl *control = new QTextControl; + QTextDocument *doc = control->document(); + doc->setHtml(m_shortLorem); + } +} + +void tst_QText::paintControlToPixmap() +{ + QTextControl *control = new QTextControl; + QTextDocument *doc = control->document(); + doc->setHtml(m_shortLorem); + doc->setTextWidth(300); + QSize size = doc->size().toSize(); + + QBENCHMARK { + QPixmap img(size); + img.fill(Qt::transparent); + QPainter p(&img); + control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size))); + } +} + +void tst_QText::paintControlToPixmap_painterFill() +{ + QTextControl *control = new QTextControl; + QTextDocument *doc = control->document(); + doc->setHtml(m_shortLorem); + doc->setTextWidth(300); + QSize size = doc->size().toSize(); + + QBENCHMARK { + QPixmap img(size); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, img.width(), img.height(), Qt::transparent); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + control->drawContents(&p, QRectF(QPointF(0, 0), QSizeF(size))); + } +} + QTEST_MAIN(tst_QText) #include "main.moc" -- cgit v0.12