diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri index 2545c7836d6933aeb74049ed272230eb5f25f224..77a3ba64909076cba607fc3a8bf3f1dc6d287503 100644 --- a/src/qml/debugger/debugger.pri +++ b/src/qml/debugger/debugger.pri @@ -34,8 +34,3 @@ HEADERS += \ $$PWD/qqmlprofiler_p.h INCLUDEPATH += $$PWD - -!contains(DEFINES, QT_QML_NO_DEBUGGER): static { - DEFINES += QML_DEBUGGER_EMBED - include(../../plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri) -} diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc index 51525b8f579b44adcf2129708979c4b4827124bb..0ec4507450f22cd18a8f67d88a60505634818845 100644 --- a/src/quick/doc/src/examples.qdoc +++ b/src/quick/doc/src/examples.qdoc @@ -72,8 +72,8 @@ The following pages show how to develop Qt applications using \l{Qt Creator Manual}{Qt Creator} and Qt Quick. The pages demonstrate various steps such as use cases and introductory material. For more information about Qt Quick Applications and related modules, visit the \l{QML Applications} page. -\div {class="landingicons"} - \div {class="icons1of3"} +\div {class="multi-column"} + \div {class="doc-column"} \b{Development Environment} \list \li \l{Qt Creator: Creating Qt Quick Projects}{Creating Qt Quick Projects} @@ -84,7 +84,7 @@ steps such as use cases and introductory material. For more information about Qt \li \l{Qt Creator: Using QML Modules with Plugins}{Using QML Modules with Plugins} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{Beginning with QML and Qt Quick} \list \li \l{First Steps with QML} @@ -92,7 +92,7 @@ steps such as use cases and introductory material. For more information about Qt \li \l{QML Advanced Tutorial}{SameGame} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{Use Cases} \list \li \l{qtquick-usecase-visual.html}{Visual types in QML} @@ -120,8 +120,8 @@ Examples are small applications which show how to implement various Qt Quick features. The examples run on various platforms and are opened from within Qt Creator. -\div {class="landingicons"} - \div {class="icons1of3"} +\div {class="multi-column"} + \div {class="doc-column"} \b{QML Types and Controls} \list \li \l{Qt Quick Controls - Gallery}{Controls Gallery} @@ -132,7 +132,7 @@ Creator. \li \l{Qt Quick Examples - Toggle Switch}{Custom Toggle Switch} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{Layouts and Views} \list \li \l{Qt Quick Controls - Basic Layouts Example}{Basic Layouts} @@ -142,7 +142,7 @@ Creator. \li \l{Qt Quick Examples - Right to Left}{Right-to-Left and Text Layout} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{Image and Graphics} \list \li \l{Qt Quick Examples - Image Elements}{Image Elements} @@ -153,8 +153,8 @@ Creator. \enddiv \enddiv -\div {class="landingicons"} - \div {class="icons1of3"} +\div {class="multi-column"} + \div {class="doc-column"} \b{Keyboard, Focus, and Touch} \list \li \l{Qt Quick Examples - Key Interaction}{Key Interaction} @@ -162,7 +162,7 @@ Creator. \li \l{Qt Quick Controls - Touch Gallery}{Touch Gallery} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{System and Events} \list \li \l{Qt Quick Examples - Threading}{Threading} @@ -171,7 +171,7 @@ Creator. \li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop} \endlist \enddiv - \div {class="icons1of3"} + \div {class="doc-column"} \b{Scene Graph} \list \li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML} diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc index 4d3341aac45779ccd96df480e1587c7327215d75..cc602d4aeeb759b1388d562170876287000273dc 100644 --- a/src/quick/doc/src/qmltypereference.qdoc +++ b/src/quick/doc/src/qmltypereference.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! -\qmlmodule QtQuick 2.3 +\qmlmodule QtQuick 2.4 \title Qt Quick QML Types \ingroup qmlmodules \brief Provides graphical QML types. @@ -34,11 +34,11 @@ The \l{Qt Quick} module provides graphical primitive types. These types are only available in a QML document if that document imports the \c QtQuick namespace. -The current version of the \c QtQuick module is version 2.3, and thus it may be +The current version of the \c QtQuick module is version 2.4, and thus it may be imported via the following statement: \qml -import QtQuick 2.3 +import QtQuick 2.4 \endqml Visit the \l {Qt Quick} module documentation for more diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 07b8958664f8670cd3891d610b47fd898ac9a991..38bbc6689662e4e8153cd1f5b9e92a3701a6a04f 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -540,390 +540,90 @@ void QQuickBorderImage::doUpdate() update(); } -QImage QQuickBorderImage::shallowCopy(const QImage &image, const QRect &rect) -{ - if (image.depth() == 1) { - return image.copy(rect); - } else { - const uchar *bits = image.constBits() + image.bytesPerLine() * rect.y() + (image.depth() / 8) * rect.x(); - return QImage(bits, rect.width(), rect.height(), image.bytesPerLine(), image.format()); - } -} - QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { Q_D(QQuickBorderImage); - if (!d->pix.isReady() || width() <= 0 || height() <= 0) { + QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window()); + + if (!texture || width() <= 0 || height() <= 0) { delete oldNode; return 0; } - // Don't implicitly create the scalegrid in the rendering thread... - QRectF innerSourceRect(0, 0, 1, 1); - QRectF innerTargetRect(0, 0, width(), height()); - int borderLeft = 0, borderTop = 0, borderRight = 0, borderBottom = 0; - - bool updateNode = !oldNode; - if (d->border) { - const QQuickScaleGrid *border = d->getScaleGrid(); - - borderLeft = qBound(0, border->left(), d->pix.width()); - borderTop = qBound(0, border->top(), d->pix.height()); - borderRight = d->pix.rect().width() - qBound(0, border->right(), d->pix.rect().width() - borderLeft); - borderBottom = d->pix.rect().height() - qBound(0, border->bottom(), d->pix.rect().height() - borderTop); - - innerSourceRect = QRectF(borderLeft / qreal(d->pix.width()), - borderTop / qreal(d->pix.height()), - qMax<qreal>(0, borderRight - borderLeft) / d->pix.width(), - qMax<qreal>(0, borderBottom - borderTop) / d->pix.height()); - innerTargetRect = QRectF(borderLeft, - borderTop, - qMax<qreal>(0, width() - border->right() - border->left()), - qMax<qreal>(0, height() - border->bottom() - border->top())); - - QSizeF newSize(width(), height()); - if (innerSourceRect != d->oldInnerSourceRect - || innerTargetRect != d->oldInnerTargetRect - || newSize != d->oldSize) { - updateNode = true; - } - - d->oldInnerSourceRect = innerSourceRect; - d->oldInnerTargetRect = innerTargetRect; - d->oldSize = newSize; - } + QSGImageNode *node = static_cast<QSGImageNode *>(oldNode); bool updatePixmap = d->pixmapChanged; d->pixmapChanged = false; - if (updateNode) { - delete oldNode; - oldNode = new QSGNode; + if (!node) { + node = d->sceneGraphContext()->createImageNode(); updatePixmap = true; - - for (int i=0; i<9; ++i) - d->regions[i].node = 0; - - if (innerSourceRect.left() > 0) { - if (innerSourceRect.top() > 0) { - QRectF rect(0, - 0, - innerTargetRect.left(), - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[0].node = d->sceneGraphContext()->createImageNode(); - d->regions[0].node->setTargetRect(rect); - d->regions[0].node->setInnerTargetRect(rect); - d->regions[0].targetRect = rect; - } - } - - if (innerSourceRect.bottom() < 1) { - QRectF rect(0, - innerTargetRect.bottom(), - innerTargetRect.left(), - height() - innerTargetRect.height() - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[6].node = d->sceneGraphContext()->createImageNode(); - d->regions[6].node->setTargetRect(rect); - d->regions[6].node->setInnerTargetRect(rect); - d->regions[6].targetRect = rect; - } - } - - if (innerSourceRect.top() < innerSourceRect.bottom()) { - QRectF rect(0, - innerTargetRect.top(), - innerTargetRect.left(), - innerTargetRect.height()); - - if (!rect.isEmpty()) { - d->regions[3].node = d->sceneGraphContext()->createImageNode(); - d->regions[3].node->setTargetRect(rect); - d->regions[3].node->setInnerTargetRect(rect); - d->regions[3].targetRect = rect; - } - } - } - - if (innerSourceRect.right() < 1) { - if (innerSourceRect.top() > 0) { - QRectF rect(innerTargetRect.right(), - 0, - width() - innerTargetRect.width() - innerTargetRect.left(), - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[2].node = d->sceneGraphContext()->createImageNode(); - d->regions[2].node->setTargetRect(rect); - d->regions[2].node->setInnerTargetRect(rect); - d->regions[2].targetRect = rect; - } - } - - if (innerSourceRect.bottom() < 1) { - QRectF rect(innerTargetRect.right(), - innerTargetRect.bottom(), - width() - innerTargetRect.width() - innerTargetRect.left(), - height() - innerTargetRect.height() - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[8].node = d->sceneGraphContext()->createImageNode(); - d->regions[8].node->setTargetRect(rect); - d->regions[8].node->setInnerTargetRect(rect); - d->regions[8].targetRect = rect; - } - } - - if (innerSourceRect.top() < innerSourceRect.bottom()) { - QRectF rect(innerTargetRect.right(), - innerTargetRect.top(), - width() - innerTargetRect.width() - innerTargetRect.left(), - innerTargetRect.height()); - - if (!rect.isEmpty()) { - d->regions[5].node = d->sceneGraphContext()->createImageNode(); - d->regions[5].node->setTargetRect(rect); - d->regions[5].node->setInnerTargetRect(rect); - d->regions[5].targetRect = rect; - } - } - } - - if (innerSourceRect.top() > 0 && innerSourceRect.left() < innerSourceRect.right()) { - QRectF rect(innerTargetRect.left(), - 0, - innerTargetRect.width(), - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[1].node = d->sceneGraphContext()->createImageNode(); - d->regions[1].node->setTargetRect(rect); - d->regions[1].node->setInnerTargetRect(rect); - d->regions[1].targetRect = rect; - } - } - - if (innerSourceRect.bottom() < 1 && innerSourceRect.left() < innerSourceRect.right()) { - QRectF rect(innerTargetRect.left(), - innerTargetRect.bottom(), - innerTargetRect.width(), - height() - innerTargetRect.height() - innerTargetRect.top()); - - if (!rect.isEmpty()) { - d->regions[7].node = d->sceneGraphContext()->createImageNode(); - d->regions[7].node->setTargetRect(rect); - d->regions[7].node->setInnerTargetRect(rect); - d->regions[7].targetRect = rect; - } - } - - if (innerSourceRect.left() < innerSourceRect.right() - && innerSourceRect.top() < innerSourceRect.bottom()) { - if (!innerTargetRect.isEmpty()) { - d->regions[4].node = d->sceneGraphContext()->createImageNode(); - d->regions[4].node->setInnerTargetRect(innerTargetRect); - d->regions[4].node->setTargetRect(innerTargetRect); - d->regions[4].targetRect = innerTargetRect; - } - } - - for (int i=0; i<9; ++i) { - if (d->regions[i].node != 0) - oldNode->appendChildNode(d->regions[i].node); - } - } - - - QImage image = d->pix.image(); - - if (d->regions[0].node != 0) { - if (updatePixmap) - d->regions[0].image = shallowCopy(image, QRect(QPoint(0, 0), QSize(borderLeft, borderTop))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingLeft | QSGImageNode::AntialiasingTop); - if (d->regions[1].node == 0 && d->regions[2].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[3].node == 0 && d->regions[6].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - d->regions[0].node->setAntialiasing(antialiasing); } - if (d->regions[1].node != 0) { - if (updatePixmap) - d->regions[1].image = shallowCopy(image, QRect(QPoint(borderLeft, 0), QSize(borderRight - borderLeft, borderTop))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingTop; - if (d->regions[0].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[2].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[4].node == 0 && d->regions[7].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - d->regions[1].node->setAntialiasing(antialiasing); - } - - if (d->regions[2].node != 0) { - if (updatePixmap) - d->regions[2].image = shallowCopy(image, QRect(QPoint(borderRight, 0), QSize(d->pix.rect().width() - borderRight, borderTop))); + if (updatePixmap) + node->setTexture(texture); - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingTop | QSGImageNode::AntialiasingRight); - if (d->regions[0].node == 0 && d->regions[1].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[5].node == 0 && d->regions[8].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - d->regions[2].node->setAntialiasing(antialiasing); - } - - if (d->regions[3].node != 0) { - if (updatePixmap) - d->regions[3].image = shallowCopy(image, QRect(QPoint(0, borderTop), QSize(borderLeft, borderBottom - borderTop))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingLeft; - if (d->regions[4].node == 0 && d->regions[5].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[6].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - if (d->regions[0].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - d->regions[3].node->setAntialiasing(antialiasing); + // Don't implicitly create the scalegrid in the rendering thread... + QRectF innerSourceRect(0, 0, 1, 1); + QRectF targetRect(0, 0, width(), height()); + QRectF innerTargetRect = targetRect; + if (d->border) { + const QQuickScaleGrid *border = d->getScaleGrid(); + innerSourceRect = QRectF(border->left() / qreal(d->pix.width()), + border->top() / qreal(d->pix.height()), + qMax<qreal>(0, d->pix.width() - border->right() - border->left()) / d->pix.width(), + qMax<qreal>(0, d->pix.height() - border->bottom() - border->top()) / d->pix.height()); + innerTargetRect = QRectF(border->left(), + border->top(), + qMax<qreal>(0, width() - border->right() - border->left()), + qMax<qreal>(0, height() - border->bottom() - border->top())); } - - if (d->regions[4].node != 0) { - if (updatePixmap) { - if (innerSourceRect == QRectF(0, 0, 1, 1)) { - d->regions[4].image = image; - } else { - d->regions[4].image = shallowCopy(image, QRect(QPoint(borderLeft, borderTop), QSize(borderRight - borderLeft, borderBottom - borderTop))); - } + qreal hTiles = 1; + qreal vTiles = 1; + if (innerSourceRect.width() != 0) { + switch (d->horizontalTileMode) { + case QQuickBorderImage::Repeat: + hTiles = innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width()); + break; + case QQuickBorderImage::Round: + hTiles = qCeil(innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width())); + break; + default: + break; } - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingNone; - if (d->regions[3].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[5].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[1].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - if (d->regions[7].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - d->regions[4].node->setAntialiasing(antialiasing); } - - if (d->regions[5].node != 0) { - if (updatePixmap) - d->regions[5].image = shallowCopy(image, QRect(QPoint(borderRight, borderTop), QSize(d->pix.rect().width() - borderRight, borderBottom - borderTop))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingRight; - if (d->regions[4].node == 0 && d->regions[3].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[2].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - if (d->regions[8].node == 0) - antialiasing |= QSGImageNode::AntialiasingBottom; - d->regions[5].node->setAntialiasing(antialiasing); - } - - if (d->regions[6].node != 0) { - if (updatePixmap) - d->regions[6].image = shallowCopy(image, QRect(QPoint(0, borderBottom), QSize(borderLeft, d->pix.rect().height() - borderBottom))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingLeft); - if (d->regions[7].node == 0 && d->regions[8].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[3].node == 0 && d->regions[0].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - d->regions[6].node->setAntialiasing(antialiasing); - } - - if (d->regions[7].node != 0) { - if (updatePixmap) - d->regions[7].image = shallowCopy(image, QRect(QPoint(borderLeft, borderBottom), QSize(borderRight - borderLeft, d->pix.rect().height() - borderBottom))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingBottom; - if (d->regions[6].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[8].node == 0) - antialiasing |= QSGImageNode::AntialiasingRight; - if (d->regions[4].node == 0 && d->regions[1].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - d->regions[7].node->setAntialiasing(antialiasing); - } - - if (d->regions[8].node != 0) { - if (updatePixmap) - d->regions[8].image = shallowCopy(image, QRect(QPoint(borderRight, borderBottom), QSize(d->pix.rect().width() - borderRight, d->pix.rect().height() - borderBottom))); - - QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingBottom | QSGImageNode::AntialiasingRight); - if (d->regions[7].node == 0 && d->regions[6].node == 0) - antialiasing |= QSGImageNode::AntialiasingLeft; - if (d->regions[5].node == 0 && d->regions[2].node == 0) - antialiasing |= QSGImageNode::AntialiasingTop; - d->regions[8].node->setAntialiasing(antialiasing); + if (innerSourceRect.height() != 0) { + switch (d->verticalTileMode) { + case QQuickBorderImage::Repeat: + vTiles = innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height()); + break; + case QQuickBorderImage::Round: + vTiles = qCeil(innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height())); + break; + default: + break; + } } - for (int i=0; i<9; ++i) { - if (d->regions[i].node != 0) { - if (updatePixmap) { - QQuickTextureFactory *textureFactory = QSGContext::createTextureFactoryFromImage(d->regions[i].image); - if (textureFactory == 0) - textureFactory = new QQuickDefaultTextureFactory(d->regions[i].image); - d->regions[i].textureFactory.reset(textureFactory); - d->regions[i].node->setTexture(d->sceneGraphRenderContext()->textureForFactory(d->regions[i].textureFactory.data(), - window())); - } - - d->regions[i].node->setInnerSourceRect(QRectF(0, 0, 1, 1)); - d->regions[i].node->setMipmapFiltering(QSGTexture::None); - d->regions[i].node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest); - d->regions[i].node->setMirror(d->mirror); - - - qreal hTiles = 1; - qreal vTiles = 1; - - if (innerSourceRect.width() != 0) { - switch (d->horizontalTileMode) { - case QQuickBorderImage::Repeat: - hTiles = d->regions[i].targetRect.width() / qreal(d->regions[i].image.width()); - break; - case QQuickBorderImage::Round: - hTiles = qCeil(d->regions[i].targetRect.width() / qreal(d->regions[i].image.width())); - break; - default: - break; - } - } - - if (innerSourceRect.height() != 0) { - switch (d->verticalTileMode) { - case QQuickBorderImage::Repeat: - vTiles = d->regions[i].targetRect.height() / qreal(d->regions[i].image.height()); - break; - case QQuickBorderImage::Round: - vTiles = qCeil(d->regions[i].targetRect.height() / qreal(d->regions[i].image.height())); - break; - default: - break; - } - } - - if (vTiles > 1 || hTiles > 1) { - d->regions[i].node->setHorizontalWrapMode(QSGTexture::Repeat); - d->regions[i].node->setVerticalWrapMode(QSGTexture::Repeat); - } else { - d->regions[i].node->setHorizontalWrapMode(QSGTexture::ClampToEdge); - d->regions[i].node->setVerticalWrapMode(QSGTexture::ClampToEdge); - } - - d->regions[i].node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles)); - d->regions[i].node->update(); - } + node->setTargetRect(targetRect); + node->setInnerSourceRect(innerSourceRect); + node->setInnerTargetRect(innerTargetRect); + node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles)); + node->setMirror(d->mirror); + + node->setMipmapFiltering(QSGTexture::None); + node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest); + if (innerSourceRect == QRectF(0, 0, 1, 1) && (vTiles > 1 || hTiles > 1)) { + node->setHorizontalWrapMode(QSGTexture::Repeat); + node->setVerticalWrapMode(QSGTexture::Repeat); + } else { + node->setHorizontalWrapMode(QSGTexture::ClampToEdge); + node->setVerticalWrapMode(QSGTexture::ClampToEdge); } + node->setAntialiasing(d->antialiasing); + node->update(); - return oldNode; + return node; } void QQuickBorderImage::pixmapChange() diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h index 1d0898115ddbef91cfd5174152ee204fe4e1c361..6a2469adc2609f7d4b82189d91abbeebd1abb5fe 100644 --- a/src/quick/items/qquickborderimage_p.h +++ b/src/quick/items/qquickborderimage_p.h @@ -87,8 +87,6 @@ private Q_SLOTS: void sciRequestFinished(); private: - static QImage shallowCopy(const QImage &image, const QRect &rect); - Q_DISABLE_COPY(QQuickBorderImage) Q_DECLARE_PRIVATE(QQuickBorderImage) }; diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h index bda2867696fb1a8fae0ee2f82554dfa7e65af08a..d5b959fd9f4dba90463edea787e77cfeac021f1d 100644 --- a/src/quick/items/qquickborderimage_p_p.h +++ b/src/quick/items/qquickborderimage_p_p.h @@ -89,16 +89,6 @@ public: QQuickBorderImage::TileMode verticalTileMode; int redirectCount; - struct BorderImageRegion - { - BorderImageRegion() : node(0), textureFactory(0) {} - QImage image; - QSGImageNode *node; - QScopedPointer<QQuickTextureFactory> textureFactory; - QRectF targetRect; - }; - BorderImageRegion regions[9]; - bool pixmapChanged : 1; }; diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index 21d11a74481387263f7cde1f95797d77806ab48c..f30eacb4ac1047f7ee3d614ad8274a4e3bd350ab 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -75,9 +75,6 @@ public: QSize sourcesize; QSize oldSourceSize; qreal devicePixelRatio; - QRectF oldInnerSourceRect; - QRectF oldInnerTargetRect; - QSizeF oldSize; bool async : 1; bool cache : 1; bool mirror: 1; diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index bfa2fccd67d0fe62eb92fc851d23f60a1e7d84f8..87255f4bd95d11ae15d648e8b3628b6b826be8f2 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -79,6 +79,7 @@ QQuickTextPrivate::QQuickTextPrivate() , requireImplicitSize(false), implicitWidthValid(false), implicitHeightValid(false) , truncated(false), hAlignImplicit(true), rightToLeftText(false) , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false) + , polishSize(false) { implicitAntialiasing = true; } @@ -356,6 +357,8 @@ void QQuickTextPrivate::updateLayout() textHasChanged = true; updateLayout(); } + + q->polish(); } void QQuickText::imageDownloadFinished() @@ -2248,13 +2251,22 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data node->addImage(QRectF(img->pos.x() + dx, img->pos.y() + dy, pix->width(), pix->height()), pix->image()); } } + + // The font caches have now been initialized on the render thread, so they have to be + // invalidated before we can use them from the main thread again. + invalidateFontCaches(); + return node; } void QQuickText::updatePolish() { Q_D(QQuickText); - d->updateSize(); + if (d->polishSize) { + d->updateSize(); + d->polishSize = false; + } + invalidateFontCaches(); } /*! @@ -2381,6 +2393,7 @@ void QQuickText::setFontSizeMode(FontSizeMode mode) if (d->fontSizeMode() == mode) return; + d->polishSize = true; polish(); d->extra.value().fontSizeMode = mode; @@ -2409,8 +2422,10 @@ void QQuickText::setMinimumPixelSize(int size) if (d->minimumPixelSize() == size) return; - if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) + if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) { + d->polishSize = true; polish(); + } d->extra.value().minimumPixelSize = size; emit minimumPixelSizeChanged(); } @@ -2437,8 +2452,10 @@ void QQuickText::setMinimumPointSize(int size) if (d->minimumPointSize() == size) return; - if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) + if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) { + d->polishSize = true; polish(); + } d->extra.value().minimumPointSize = size; emit minimumPointSizeChanged(); } @@ -2699,4 +2716,26 @@ QString QQuickText::linkAt(qreal x, qreal y) const return d->anchorAt(QPointF(x, y)); } +/*! + * \internal + * + * Invalidates font caches owned by the text objects owned by the element + * to work around the fact that text objects cannot be used from multiple threads. + */ +void QQuickText::invalidateFontCaches() +{ + Q_D(QQuickText); + + if (d->richText && d->extra->doc != 0) { + QTextBlock block; + for (block = d->extra->doc->firstBlock(); block.isValid(); block = block.next()) { + if (block.layout() != 0 && block.layout()->engine() != 0) + block.layout()->engine()->resetFontEngineCache(); + } + } else { + if (d->layout.engine() != 0) + d->layout.engine()->resetFontEngineCache(); + } +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h index c9f64d3fabc2069f4e30fb5dc33cacdce9fabc62..c3fa9e6935195295104dd3d64428ef015c33a80b 100644 --- a/src/quick/items/qquicktext_p.h +++ b/src/quick/items/qquicktext_p.h @@ -245,6 +245,7 @@ protected: void hoverEnterEvent(QHoverEvent *event); void hoverMoveEvent(QHoverEvent *event); void hoverLeaveEvent(QHoverEvent *event); + void invalidateFontCaches(); private Q_SLOTS: void q_imagesLoaded(); diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h index 022c2ac9d53076f9401648d6e0f66f8f4d7b0c81..d645ce5ed5f0ca18390de32098b93b9ae78fbcb3 100644 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@ -151,6 +151,7 @@ public: bool textHasChanged:1; bool needToUpdateLayout:1; bool formatModifiesFontSize:1; + bool polishSize:1; // Workaround for problem with polish called after updateSize (QTBUG-42636) static const QChar elideChar; diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index aca7150ca2dff965c9fc0bc5b1ca498ab59fc28f..b950f962773786cd14b0ce30cc166a05b53f68ea 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1739,6 +1739,7 @@ void QQuickTextEdit::triggerPreprocess() Q_D(QQuickTextEdit); if (d->updateType == QQuickTextEditPrivate::UpdateNone) d->updateType = QQuickTextEditPrivate::UpdateOnlyPreprocess; + polish(); update(); } @@ -1758,6 +1759,25 @@ static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topL node->setMatrix(transformMatrix); } +/*! + * \internal + * + * Invalidates font caches owned by the text objects owned by the element + * to work around the fact that text objects cannot be used from multiple threads. + */ +void QQuickTextEdit::invalidateFontCaches() +{ + Q_D(QQuickTextEdit); + if (d->document == 0) + return; + + QTextBlock block; + for (block = d->document->firstBlock(); block.isValid(); block = block.next()) { + if (block.layout() != 0 && block.layout()->engine() != 0) + block.layout()->engine()->resetFontEngineCache(); + } +} + QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) { Q_UNUSED(updatePaintNodeData); @@ -1911,9 +1931,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * rootNode->resetCursorNode(cursor); } + invalidateFontCaches(); + return rootNode; } +void QQuickTextEdit::updatePolish() +{ + invalidateFontCaches(); +} + /*! \qmlproperty bool QtQuick::TextEdit::canPaste @@ -2079,6 +2106,7 @@ void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded) markDirtyNodesForRange(pos, editRange, delta); + polish(); if (isComponentComplete()) { d->updateType = QQuickTextEditPrivate::UpdatePaintNode; update(); @@ -2106,6 +2134,7 @@ void QQuickTextEdit::updateSelection() // No need for node updates when we go from an empty selection to another empty selection if (d->control->textCursor().hasSelection() || d->hadSelection) { markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0); + polish(); if (isComponentComplete()) { d->updateType = QQuickTextEditPrivate::UpdatePaintNode; update(); @@ -2246,6 +2275,7 @@ void QQuickTextEdit::updateWholeDocument() node->setDirty(); } + polish(); if (isComponentComplete()) { d->updateType = QQuickTextEditPrivate::UpdatePaintNode; update(); @@ -2260,6 +2290,7 @@ void QQuickTextEdit::invalidateBlock(const QTextBlock &block) void QQuickTextEdit::updateCursor() { Q_D(QQuickTextEdit); + polish(); if (isComponentComplete()) { d->updateType = QQuickTextEditPrivate::UpdatePaintNode; update(); diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index 54e6dd229af48f2b41e1ed3a4751109c104a070c..5d1c026c5cf5ef8d40cd33bdd683f90acb1b1318 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -330,6 +330,7 @@ private Q_SLOTS: private: void markDirtyNodesForRange(int start, int end, int charDelta); void updateTotalLines(); + void invalidateFontCaches(); protected: virtual void geometryChanged(const QRectF &newGeometry, @@ -354,6 +355,7 @@ protected: void inputMethodEvent(QInputMethodEvent *e); #endif QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData); + void updatePolish(); friend class QQuickTextUtil; friend class QQuickTextDocument; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 1f03fb21e21c224dd9fda36604f9b0db7b41e684..a9c60273d2b8de0cba65d548ff1cc16373ff5cd7 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -56,6 +56,8 @@ #include "qquickaccessibleattached_p.h" #endif +#include <QtGui/private/qtextengine_p.h> + QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) @@ -362,6 +364,7 @@ void QQuickTextInput::setColor(const QColor &c) d->color = c; d->textLayoutDirty = true; d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); emit colorChanged(); } @@ -389,6 +392,7 @@ void QQuickTextInput::setSelectionColor(const QColor &color) if (d->hasSelectedText()) { d->textLayoutDirty = true; d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); } emit selectionColorChanged(); @@ -414,6 +418,7 @@ void QQuickTextInput::setSelectedTextColor(const QColor &color) if (d->hasSelectedText()) { d->textLayoutDirty = true; d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); } emit selectedTextColorChanged(); @@ -723,6 +728,7 @@ void QQuickTextInput::setCursorVisible(bool on) if (!d->cursorItem) { d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0); d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); } emit cursorVisibleChanged(d->cursorVisible); @@ -1830,9 +1836,23 @@ void QQuickTextInput::triggerPreprocess() Q_D(QQuickTextInput); if (d->updateType == QQuickTextInputPrivate::UpdateNone) d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess; + polish(); update(); } +void QQuickTextInput::updatePolish() +{ + invalidateFontCaches(); +} + +void QQuickTextInput::invalidateFontCaches() +{ + Q_D(QQuickTextInput); + + if (d->m_textLayout.engine() != 0) + d->m_textLayout.engine()->resetFontEngineCache(); +} + QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) { Q_UNUSED(data); @@ -1891,6 +1911,8 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData d->textLayoutDirty = false; } + invalidateFontCaches(); + return node; } @@ -2651,6 +2673,7 @@ void QQuickTextInput::updateCursorRectangle(bool scroll) d->updateVerticalScroll(); } d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); emit cursorRectangleChanged(); if (d->cursorItem) { @@ -2668,6 +2691,7 @@ void QQuickTextInput::selectionChanged() Q_D(QQuickTextInput); d->textLayoutDirty = true; //TODO: Only update rect in selection d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); emit selectedTextChanged(); @@ -2879,6 +2903,7 @@ void QQuickTextInputPrivate::updateLayout() contentSize = QSizeF(width, height); updateType = UpdatePaintNode; + q->polish(); q->update(); if (!requireImplicitWidth && !q->widthValid()) @@ -4167,6 +4192,7 @@ void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec) m_blinkTimer = 0; if (m_blinkStatus == 1) { updateType = UpdatePaintNode; + q->polish(); q->update(); } } @@ -4179,6 +4205,7 @@ void QQuickTextInput::timerEvent(QTimerEvent *event) if (event->timerId() == d->m_blinkTimer) { d->m_blinkStatus = !d->m_blinkStatus; d->updateType = QQuickTextInputPrivate::UpdatePaintNode; + polish(); update(); } else if (event->timerId() == d->m_passwordEchoTimer.timerId()) { d->m_passwordEchoTimer.stop(); diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 4b945305870d35b07c9d0ffc8458e2327208aede..2386fc564299041496e52c2a8235b8ab65055f27 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -314,6 +314,9 @@ Q_SIGNALS: #endif void renderTypeChanged(); +private: + void invalidateFontCaches(); + protected: virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); @@ -332,6 +335,7 @@ protected: void focusInEvent(QFocusEvent *event); void timerEvent(QTimerEvent *event); QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data); + void updatePolish(); public Q_SLOTS: void selectAll(); diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 962fc5a98a1715b1d8c50d30e495ee1eb74b8c91..ef21385ee6511c55be3c333a480f28f913c3243c 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -126,17 +126,6 @@ public: class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode { public: - enum AntialiasingFlag - { - AntialiasingNone = 0, - AntialiasingLeft = 1, - AntialiasingRight = 2, - AntialiasingTop = 4, - AntialiasingBottom = 8, - AntialiasingAll = AntialiasingLeft | AntialiasingRight | AntialiasingBottom | AntialiasingTop - }; - Q_DECLARE_FLAGS(AntialiasingFlags, AntialiasingFlag) - virtual void setTargetRect(const QRectF &rect) = 0; virtual void setInnerTargetRect(const QRectF &rect) = 0; virtual void setInnerSourceRect(const QRectF &rect) = 0; @@ -151,7 +140,6 @@ public: virtual void setFiltering(QSGTexture::Filtering filtering) = 0; virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0; virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0; - virtual void setAntialiasing(AntialiasingFlags flags) { Q_UNUSED(flags); } virtual void update() = 0; diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index 69df506d2aa02e99f71b476d2063d28bba9b8be6..7f85c31ccbf3151b1b9084c65ac54649c4713e6a 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -140,11 +140,10 @@ void SmoothTextureMaterialShader::initialize() QSGDefaultImageNode::QSGDefaultImageNode() : m_innerSourceRect(0, 0, 1, 1) , m_subSourceRect(0, 0, 1, 1) + , m_antialiasing(false) , m_mirror(false) , m_dirtyGeometry(false) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) - , m_antialiasing(AntialiasingNone) - { setMaterial(&m_materialO); setOpaqueMaterial(&m_material); @@ -250,20 +249,10 @@ void QSGDefaultImageNode::setTexture(QSGTexture *texture) void QSGDefaultImageNode::setAntialiasing(bool antialiasing) { - AntialiasingFlags antialiasingFlags = antialiasing - ? AntialiasingAll - : AntialiasingNone; - - setAntialiasing(antialiasingFlags); -} - -void QSGDefaultImageNode::setAntialiasing(AntialiasingFlags antialiasingFlags) -{ - if (antialiasingFlags == m_antialiasing) + if (antialiasing == m_antialiasing) return; - - m_antialiasing = antialiasingFlags; - if (m_antialiasing != AntialiasingNone) { + m_antialiasing = antialiasing; + if (m_antialiasing) { setMaterial(&m_smoothMaterial); setOpaqueMaterial(0); setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); @@ -375,14 +364,11 @@ void QSGDefaultImageNode::updateGeometry() } // An image can be rendered as a single quad if: - // - There is antialiasing on all or no edges // - There are no margins, and either: // - the image isn't repeated // - the source rectangle fills the entire texture so that texture wrapping can be used, // and NPOT is supported - if (!hasMargins - && (m_antialiasing == AntialiasingAll || m_antialiasing == AntialiasingNone) - && (!hasTiles || (fullTexture && wrapSupported))) { + if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) { QRectF sr; if (!fullTexture) { sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), @@ -561,35 +547,10 @@ void QSGDefaultImageNode::updateGeometry() topDv = bottomDv *= 0.5f; } - if (!m_antialiasing.testFlag(AntialiasingTop)) { - topDy = 0.0f; - topDv = 0.0f; - } - - if (!m_antialiasing.testFlag(AntialiasingBottom)) { - bottomDy = 0.0f; - bottomDv = 0.0f; - } - - if (!m_antialiasing.testFlag(AntialiasingLeft)) { - leftDx = 0.0f; - leftDu = 0.0f; - } - - if (!m_antialiasing.testFlag(AntialiasingRight)) { - rightDx = 0.0f; - rightDu = 0.0f; - } - // This delta is how much the fuzziness can reach out from the image. float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) ? m_targetRect.width() : m_targetRect.height()) * 0.5f; - float deltaTop = m_antialiasing.testFlag(AntialiasingTop) ? delta : 0.0f; - float deltaBottom = m_antialiasing.testFlag(AntialiasingBottom) ? delta : 0.0f; - float deltaLeft = m_antialiasing.testFlag(AntialiasingLeft) ? delta : 0.0f; - float deltaRight = m_antialiasing.testFlag(AntialiasingRight) ? delta : 0.0f; - quint16 index = 0; ys = yData.data(); for (int j = 0; j < vCells; ++j, ys += 2) { @@ -639,28 +600,28 @@ void QSGDefaultImageNode::updateGeometry() if (isTop) { vertices[topLeft].dy = vertices[topRight].dy = topDy; vertices[topLeft].dv = vertices[topRight].dv = topDv; - vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -deltaTop; + vertices[topLeft + 1].dy = vertices[topRight + 1].dy = -delta; appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight); } if (isBottom) { vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; - vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = deltaBottom; + vertices[bottomLeft + 1].dy = vertices[bottomRight + 1].dy = delta; appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1); } if (isLeft) { vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; vertices[topLeft].du = vertices[bottomLeft].du = leftDu; - vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -deltaLeft; + vertices[topLeft + 1].dx = vertices[bottomLeft + 1].dx = -delta; appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft); } if (isRight) { vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; vertices[topRight].du = vertices[bottomRight].du = -rightDu; - vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = deltaRight; + vertices[topRight + 1].dx = vertices[bottomRight + 1].dx = delta; appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1); } } diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h index 558e4d8ba49a88038ecc77e843228b8ff7981d80..26b087284b1f6fbffd3801d97446d7bd2e1ff153 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode_p.h +++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h @@ -62,7 +62,6 @@ public: virtual void setSubSourceRect(const QRectF &rect); virtual void setTexture(QSGTexture *t); virtual void setAntialiasing(bool antialiasing); - virtual void setAntialiasing(AntialiasingFlags antialiasing); virtual void setMirror(bool mirror); virtual void update(); @@ -85,11 +84,11 @@ private: QSGTextureMaterial m_materialO; QSGSmoothTextureMaterial m_smoothMaterial; + uint m_antialiasing : 1; uint m_mirror : 1; uint m_dirtyGeometry : 1; QSGGeometry m_geometry; - AntialiasingFlags m_antialiasing; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 070d6b82fdde93b4b6c996f3ad618677a7c63cf1..1213c7e771bcebfc8d87a7322a58b0647a22e05b 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -38,6 +38,7 @@ #include <QtGui/QScreen> #include <QtGui/QGuiApplication> +#include <QtGui/QOffscreenSurface> #include <QtQuick/private/qsgcontext_p.h> #include <QtQuick/private/qquickwindow_p.h> @@ -210,15 +211,29 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) hide(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - if (m_gl) - m_gl->makeCurrent(window); + bool current = false; + QScopedPointer<QOffscreenSurface> offscreenSurface; + if (m_gl) { + QSurface *surface = window; + // There may be no platform window if the window got closed. + if (!window->handle()) { + offscreenSurface.reset(new QOffscreenSurface); + offscreenSurface->setFormat(m_gl->format()); + offscreenSurface->create(); + surface = offscreenSurface.data(); + } + current = m_gl->makeCurrent(surface); + } + if (Q_UNLIKELY(!current)) + qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context"; + d->cleanupNodesOnShutdown(); if (m_windows.size() == 0) { d->context->invalidate(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); delete m_gl; m_gl = 0; - } else if (m_gl) { + } else if (m_gl && current) { m_gl->doneCurrent(); } } diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 69ccd7a316ae512f7994ea1ee51f7a0589ce2a15..e06f249b40cb5e280475ef4c72bd4b248978d7ab 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -494,6 +494,7 @@ int main(int argc, char *argv[]) foreach (const QString &path, files) { //QUrl::fromUserInput doesn't treat no scheme as relative file paths +#ifndef QT_NO_REGULAREXPRESSION QRegularExpression urlRe("[[:word:]]+://.*"); if (urlRe.match(path).hasMatch()) { //Treat as a URL QUrl url = QUrl::fromUserInput(path); @@ -503,7 +504,9 @@ int main(int argc, char *argv[]) ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString())); e.load(url); - } else { //Local file path + } else +#endif + { //Local file path if (verboseMode) printf("qml: loading %s\n", qPrintable(QDir::toNativeSeparators(path)));