Merge remote-tracking branch 'origin/5.4.0' into 5.4

Change-Id: I2e7fc085663e00dd0390593a91c30d23d1369c4e
This commit is contained in:
Frederik Gladhorn 2014-11-21 13:45:07 +01:00
commit 0874c2a1e5
19 changed files with 218 additions and 467 deletions

View File

@ -34,8 +34,3 @@ HEADERS += \
$$PWD/qqmlprofiler_p.h $$PWD/qqmlprofiler_p.h
INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD
!contains(DEFINES, QT_QML_NO_DEBUGGER): static {
DEFINES += QML_DEBUGGER_EMBED
include(../../plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pri)
}

View File

@ -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 \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. 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="multi-column"}
\div {class="icons1of3"} \div {class="doc-column"}
\b{Development Environment} \b{Development Environment}
\list \list
\li \l{Qt Creator: Creating Qt Quick Projects}{Creating Qt Quick Projects} \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} \li \l{Qt Creator: Using QML Modules with Plugins}{Using QML Modules with Plugins}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{Beginning with QML and Qt Quick} \b{Beginning with QML and Qt Quick}
\list \list
\li \l{First Steps with QML} \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} \li \l{QML Advanced Tutorial}{SameGame}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{Use Cases} \b{Use Cases}
\list \list
\li \l{qtquick-usecase-visual.html}{Visual types in QML} \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 features. The examples run on various platforms and are opened from within Qt
Creator. Creator.
\div {class="landingicons"} \div {class="multi-column"}
\div {class="icons1of3"} \div {class="doc-column"}
\b{QML Types and Controls} \b{QML Types and Controls}
\list \list
\li \l{Qt Quick Controls - Gallery}{Controls Gallery} \li \l{Qt Quick Controls - Gallery}{Controls Gallery}
@ -132,7 +132,7 @@ Creator.
\li \l{Qt Quick Examples - Toggle Switch}{Custom Toggle Switch} \li \l{Qt Quick Examples - Toggle Switch}{Custom Toggle Switch}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{Layouts and Views} \b{Layouts and Views}
\list \list
\li \l{Qt Quick Controls - Basic Layouts Example}{Basic Layouts} \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} \li \l{Qt Quick Examples - Right to Left}{Right-to-Left and Text Layout}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{Image and Graphics} \b{Image and Graphics}
\list \list
\li \l{Qt Quick Examples - Image Elements}{Image Elements} \li \l{Qt Quick Examples - Image Elements}{Image Elements}
@ -153,8 +153,8 @@ Creator.
\enddiv \enddiv
\enddiv \enddiv
\div {class="landingicons"} \div {class="multi-column"}
\div {class="icons1of3"} \div {class="doc-column"}
\b{Keyboard, Focus, and Touch} \b{Keyboard, Focus, and Touch}
\list \list
\li \l{Qt Quick Examples - Key Interaction}{Key Interaction} \li \l{Qt Quick Examples - Key Interaction}{Key Interaction}
@ -162,7 +162,7 @@ Creator.
\li \l{Qt Quick Controls - Touch Gallery}{Touch Gallery} \li \l{Qt Quick Controls - Touch Gallery}{Touch Gallery}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{System and Events} \b{System and Events}
\list \list
\li \l{Qt Quick Examples - Threading}{Threading} \li \l{Qt Quick Examples - Threading}{Threading}
@ -171,7 +171,7 @@ Creator.
\li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop} \li \l{Qt Quick Examples - Drag and Drop}{Drag and Drop}
\endlist \endlist
\enddiv \enddiv
\div {class="icons1of3"} \div {class="doc-column"}
\b{Scene Graph} \b{Scene Graph}
\list \list
\li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML} \li \l{Scene Graph - OpenGL Under QML}{OpenGL Under QML}

View File

@ -26,7 +26,7 @@
****************************************************************************/ ****************************************************************************/
/*! /*!
\qmlmodule QtQuick 2.3 \qmlmodule QtQuick 2.4
\title Qt Quick QML Types \title Qt Quick QML Types
\ingroup qmlmodules \ingroup qmlmodules
\brief Provides graphical QML types. \brief Provides graphical QML types.
@ -34,11 +34,11 @@
The \l{Qt Quick} module provides graphical primitive types. These types are only 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. 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: imported via the following statement:
\qml \qml
import QtQuick 2.3 import QtQuick 2.4
\endqml \endqml
Visit the \l {Qt Quick} module documentation for more Visit the \l {Qt Quick} module documentation for more

View File

@ -540,390 +540,90 @@ void QQuickBorderImage::doUpdate()
update(); 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 *) QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{ {
Q_D(QQuickBorderImage); 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; delete oldNode;
return 0; return 0;
} }
// Don't implicitly create the scalegrid in the rendering thread... QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
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;
}
bool updatePixmap = d->pixmapChanged; bool updatePixmap = d->pixmapChanged;
d->pixmapChanged = false; d->pixmapChanged = false;
if (updateNode) { if (!node) {
delete oldNode; node = d->sceneGraphContext()->createImageNode();
oldNode = new QSGNode;
updatePixmap = true; 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) if (updatePixmap)
d->regions[0].image = shallowCopy(image, QRect(QPoint(0, 0), QSize(borderLeft, borderTop))); node->setTexture(texture);
QSGImageNode::AntialiasingFlags antialiasing = QSGImageNode::AntialiasingFlags(QSGImageNode::AntialiasingLeft | QSGImageNode::AntialiasingTop); // Don't implicitly create the scalegrid in the rendering thread...
if (d->regions[1].node == 0 && d->regions[2].node == 0) QRectF innerSourceRect(0, 0, 1, 1);
antialiasing |= QSGImageNode::AntialiasingRight; QRectF targetRect(0, 0, width(), height());
if (d->regions[3].node == 0 && d->regions[6].node == 0) QRectF innerTargetRect = targetRect;
antialiasing |= QSGImageNode::AntialiasingBottom; if (d->border) {
d->regions[0].node->setAntialiasing(antialiasing); 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[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)));
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);
}
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)));
}
}
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);
}
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 hTiles = 1;
qreal vTiles = 1; qreal vTiles = 1;
if (innerSourceRect.width() != 0) { if (innerSourceRect.width() != 0) {
switch (d->horizontalTileMode) { switch (d->horizontalTileMode) {
case QQuickBorderImage::Repeat: case QQuickBorderImage::Repeat:
hTiles = d->regions[i].targetRect.width() / qreal(d->regions[i].image.width()); hTiles = innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width());
break; break;
case QQuickBorderImage::Round: case QQuickBorderImage::Round:
hTiles = qCeil(d->regions[i].targetRect.width() / qreal(d->regions[i].image.width())); hTiles = qCeil(innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width()));
break; break;
default: default:
break; break;
} }
} }
if (innerSourceRect.height() != 0) { if (innerSourceRect.height() != 0) {
switch (d->verticalTileMode) { switch (d->verticalTileMode) {
case QQuickBorderImage::Repeat: case QQuickBorderImage::Repeat:
vTiles = d->regions[i].targetRect.height() / qreal(d->regions[i].image.height()); vTiles = innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height());
break; break;
case QQuickBorderImage::Round: case QQuickBorderImage::Round:
vTiles = qCeil(d->regions[i].targetRect.height() / qreal(d->regions[i].image.height())); vTiles = qCeil(innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height()));
break; break;
default: default:
break; break;
} }
} }
if (vTiles > 1 || hTiles > 1) { node->setTargetRect(targetRect);
d->regions[i].node->setHorizontalWrapMode(QSGTexture::Repeat); node->setInnerSourceRect(innerSourceRect);
d->regions[i].node->setVerticalWrapMode(QSGTexture::Repeat); 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 { } else {
d->regions[i].node->setHorizontalWrapMode(QSGTexture::ClampToEdge); node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
d->regions[i].node->setVerticalWrapMode(QSGTexture::ClampToEdge); node->setVerticalWrapMode(QSGTexture::ClampToEdge);
} }
node->setAntialiasing(d->antialiasing);
node->update();
d->regions[i].node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles)); return node;
d->regions[i].node->update();
}
}
return oldNode;
} }
void QQuickBorderImage::pixmapChange() void QQuickBorderImage::pixmapChange()

View File

@ -87,8 +87,6 @@ private Q_SLOTS:
void sciRequestFinished(); void sciRequestFinished();
private: private:
static QImage shallowCopy(const QImage &image, const QRect &rect);
Q_DISABLE_COPY(QQuickBorderImage) Q_DISABLE_COPY(QQuickBorderImage)
Q_DECLARE_PRIVATE(QQuickBorderImage) Q_DECLARE_PRIVATE(QQuickBorderImage)
}; };

View File

@ -89,16 +89,6 @@ public:
QQuickBorderImage::TileMode verticalTileMode; QQuickBorderImage::TileMode verticalTileMode;
int redirectCount; int redirectCount;
struct BorderImageRegion
{
BorderImageRegion() : node(0), textureFactory(0) {}
QImage image;
QSGImageNode *node;
QScopedPointer<QQuickTextureFactory> textureFactory;
QRectF targetRect;
};
BorderImageRegion regions[9];
bool pixmapChanged : 1; bool pixmapChanged : 1;
}; };

View File

@ -75,9 +75,6 @@ public:
QSize sourcesize; QSize sourcesize;
QSize oldSourceSize; QSize oldSourceSize;
qreal devicePixelRatio; qreal devicePixelRatio;
QRectF oldInnerSourceRect;
QRectF oldInnerTargetRect;
QSizeF oldSize;
bool async : 1; bool async : 1;
bool cache : 1; bool cache : 1;
bool mirror: 1; bool mirror: 1;

View File

@ -79,6 +79,7 @@ QQuickTextPrivate::QQuickTextPrivate()
, requireImplicitSize(false), implicitWidthValid(false), implicitHeightValid(false) , requireImplicitSize(false), implicitWidthValid(false), implicitHeightValid(false)
, truncated(false), hAlignImplicit(true), rightToLeftText(false) , truncated(false), hAlignImplicit(true), rightToLeftText(false)
, layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false) , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false)
, polishSize(false)
{ {
implicitAntialiasing = true; implicitAntialiasing = true;
} }
@ -356,6 +357,8 @@ void QQuickTextPrivate::updateLayout()
textHasChanged = true; textHasChanged = true;
updateLayout(); updateLayout();
} }
q->polish();
} }
void QQuickText::imageDownloadFinished() 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()); 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; return node;
} }
void QQuickText::updatePolish() void QQuickText::updatePolish()
{ {
Q_D(QQuickText); Q_D(QQuickText);
if (d->polishSize) {
d->updateSize(); d->updateSize();
d->polishSize = false;
}
invalidateFontCaches();
} }
/*! /*!
@ -2381,6 +2393,7 @@ void QQuickText::setFontSizeMode(FontSizeMode mode)
if (d->fontSizeMode() == mode) if (d->fontSizeMode() == mode)
return; return;
d->polishSize = true;
polish(); polish();
d->extra.value().fontSizeMode = mode; d->extra.value().fontSizeMode = mode;
@ -2409,8 +2422,10 @@ void QQuickText::setMinimumPixelSize(int size)
if (d->minimumPixelSize() == size) if (d->minimumPixelSize() == size)
return; return;
if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
d->polishSize = true;
polish(); polish();
}
d->extra.value().minimumPixelSize = size; d->extra.value().minimumPixelSize = size;
emit minimumPixelSizeChanged(); emit minimumPixelSizeChanged();
} }
@ -2437,8 +2452,10 @@ void QQuickText::setMinimumPointSize(int size)
if (d->minimumPointSize() == size) if (d->minimumPointSize() == size)
return; return;
if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
d->polishSize = true;
polish(); polish();
}
d->extra.value().minimumPointSize = size; d->extra.value().minimumPointSize = size;
emit minimumPointSizeChanged(); emit minimumPointSizeChanged();
} }
@ -2699,4 +2716,26 @@ QString QQuickText::linkAt(qreal x, qreal y) const
return d->anchorAt(QPointF(x, y)); 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 QT_END_NAMESPACE

View File

@ -245,6 +245,7 @@ protected:
void hoverEnterEvent(QHoverEvent *event); void hoverEnterEvent(QHoverEvent *event);
void hoverMoveEvent(QHoverEvent *event); void hoverMoveEvent(QHoverEvent *event);
void hoverLeaveEvent(QHoverEvent *event); void hoverLeaveEvent(QHoverEvent *event);
void invalidateFontCaches();
private Q_SLOTS: private Q_SLOTS:
void q_imagesLoaded(); void q_imagesLoaded();

View File

@ -151,6 +151,7 @@ public:
bool textHasChanged:1; bool textHasChanged:1;
bool needToUpdateLayout:1; bool needToUpdateLayout:1;
bool formatModifiesFontSize:1; bool formatModifiesFontSize:1;
bool polishSize:1; // Workaround for problem with polish called after updateSize (QTBUG-42636)
static const QChar elideChar; static const QChar elideChar;

View File

@ -1739,6 +1739,7 @@ void QQuickTextEdit::triggerPreprocess()
Q_D(QQuickTextEdit); Q_D(QQuickTextEdit);
if (d->updateType == QQuickTextEditPrivate::UpdateNone) if (d->updateType == QQuickTextEditPrivate::UpdateNone)
d->updateType = QQuickTextEditPrivate::UpdateOnlyPreprocess; d->updateType = QQuickTextEditPrivate::UpdateOnlyPreprocess;
polish();
update(); update();
} }
@ -1758,6 +1759,25 @@ static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topL
node->setMatrix(transformMatrix); 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) QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{ {
Q_UNUSED(updatePaintNodeData); Q_UNUSED(updatePaintNodeData);
@ -1911,9 +1931,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
rootNode->resetCursorNode(cursor); rootNode->resetCursorNode(cursor);
} }
invalidateFontCaches();
return rootNode; return rootNode;
} }
void QQuickTextEdit::updatePolish()
{
invalidateFontCaches();
}
/*! /*!
\qmlproperty bool QtQuick::TextEdit::canPaste \qmlproperty bool QtQuick::TextEdit::canPaste
@ -2079,6 +2106,7 @@ void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded)
markDirtyNodesForRange(pos, editRange, delta); markDirtyNodesForRange(pos, editRange, delta);
polish();
if (isComponentComplete()) { if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode; d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update(); update();
@ -2106,6 +2134,7 @@ void QQuickTextEdit::updateSelection()
// No need for node updates when we go from an empty selection to another empty selection // No need for node updates when we go from an empty selection to another empty selection
if (d->control->textCursor().hasSelection() || d->hadSelection) { if (d->control->textCursor().hasSelection() || d->hadSelection) {
markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0); markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0);
polish();
if (isComponentComplete()) { if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode; d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update(); update();
@ -2246,6 +2275,7 @@ void QQuickTextEdit::updateWholeDocument()
node->setDirty(); node->setDirty();
} }
polish();
if (isComponentComplete()) { if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode; d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update(); update();
@ -2260,6 +2290,7 @@ void QQuickTextEdit::invalidateBlock(const QTextBlock &block)
void QQuickTextEdit::updateCursor() void QQuickTextEdit::updateCursor()
{ {
Q_D(QQuickTextEdit); Q_D(QQuickTextEdit);
polish();
if (isComponentComplete()) { if (isComponentComplete()) {
d->updateType = QQuickTextEditPrivate::UpdatePaintNode; d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
update(); update();

View File

@ -330,6 +330,7 @@ private Q_SLOTS:
private: private:
void markDirtyNodesForRange(int start, int end, int charDelta); void markDirtyNodesForRange(int start, int end, int charDelta);
void updateTotalLines(); void updateTotalLines();
void invalidateFontCaches();
protected: protected:
virtual void geometryChanged(const QRectF &newGeometry, virtual void geometryChanged(const QRectF &newGeometry,
@ -354,6 +355,7 @@ protected:
void inputMethodEvent(QInputMethodEvent *e); void inputMethodEvent(QInputMethodEvent *e);
#endif #endif
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData); QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
void updatePolish();
friend class QQuickTextUtil; friend class QQuickTextUtil;
friend class QQuickTextDocument; friend class QQuickTextDocument;

View File

@ -56,6 +56,8 @@
#include "qquickaccessibleattached_p.h" #include "qquickaccessibleattached_p.h"
#endif #endif
#include <QtGui/private/qtextengine_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
@ -362,6 +364,7 @@ void QQuickTextInput::setColor(const QColor &c)
d->color = c; d->color = c;
d->textLayoutDirty = true; d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
emit colorChanged(); emit colorChanged();
} }
@ -389,6 +392,7 @@ void QQuickTextInput::setSelectionColor(const QColor &color)
if (d->hasSelectedText()) { if (d->hasSelectedText()) {
d->textLayoutDirty = true; d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
} }
emit selectionColorChanged(); emit selectionColorChanged();
@ -414,6 +418,7 @@ void QQuickTextInput::setSelectedTextColor(const QColor &color)
if (d->hasSelectedText()) { if (d->hasSelectedText()) {
d->textLayoutDirty = true; d->textLayoutDirty = true;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
} }
emit selectedTextColorChanged(); emit selectedTextColorChanged();
@ -723,6 +728,7 @@ void QQuickTextInput::setCursorVisible(bool on)
if (!d->cursorItem) { if (!d->cursorItem) {
d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0); d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
} }
emit cursorVisibleChanged(d->cursorVisible); emit cursorVisibleChanged(d->cursorVisible);
@ -1830,9 +1836,23 @@ void QQuickTextInput::triggerPreprocess()
Q_D(QQuickTextInput); Q_D(QQuickTextInput);
if (d->updateType == QQuickTextInputPrivate::UpdateNone) if (d->updateType == QQuickTextInputPrivate::UpdateNone)
d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess; d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess;
polish();
update(); 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) QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{ {
Q_UNUSED(data); Q_UNUSED(data);
@ -1891,6 +1911,8 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
d->textLayoutDirty = false; d->textLayoutDirty = false;
} }
invalidateFontCaches();
return node; return node;
} }
@ -2651,6 +2673,7 @@ void QQuickTextInput::updateCursorRectangle(bool scroll)
d->updateVerticalScroll(); d->updateVerticalScroll();
} }
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
emit cursorRectangleChanged(); emit cursorRectangleChanged();
if (d->cursorItem) { if (d->cursorItem) {
@ -2668,6 +2691,7 @@ void QQuickTextInput::selectionChanged()
Q_D(QQuickTextInput); Q_D(QQuickTextInput);
d->textLayoutDirty = true; //TODO: Only update rect in selection d->textLayoutDirty = true; //TODO: Only update rect in selection
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
emit selectedTextChanged(); emit selectedTextChanged();
@ -2879,6 +2903,7 @@ void QQuickTextInputPrivate::updateLayout()
contentSize = QSizeF(width, height); contentSize = QSizeF(width, height);
updateType = UpdatePaintNode; updateType = UpdatePaintNode;
q->polish();
q->update(); q->update();
if (!requireImplicitWidth && !q->widthValid()) if (!requireImplicitWidth && !q->widthValid())
@ -4167,6 +4192,7 @@ void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec)
m_blinkTimer = 0; m_blinkTimer = 0;
if (m_blinkStatus == 1) { if (m_blinkStatus == 1) {
updateType = UpdatePaintNode; updateType = UpdatePaintNode;
q->polish();
q->update(); q->update();
} }
} }
@ -4179,6 +4205,7 @@ void QQuickTextInput::timerEvent(QTimerEvent *event)
if (event->timerId() == d->m_blinkTimer) { if (event->timerId() == d->m_blinkTimer) {
d->m_blinkStatus = !d->m_blinkStatus; d->m_blinkStatus = !d->m_blinkStatus;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode; d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
polish();
update(); update();
} else if (event->timerId() == d->m_passwordEchoTimer.timerId()) { } else if (event->timerId() == d->m_passwordEchoTimer.timerId()) {
d->m_passwordEchoTimer.stop(); d->m_passwordEchoTimer.stop();

View File

@ -314,6 +314,9 @@ Q_SIGNALS:
#endif #endif
void renderTypeChanged(); void renderTypeChanged();
private:
void invalidateFontCaches();
protected: protected:
virtual void geometryChanged(const QRectF &newGeometry, virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry); const QRectF &oldGeometry);
@ -332,6 +335,7 @@ protected:
void focusInEvent(QFocusEvent *event); void focusInEvent(QFocusEvent *event);
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event);
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data); QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
void updatePolish();
public Q_SLOTS: public Q_SLOTS:
void selectAll(); void selectAll();

View File

@ -126,17 +126,6 @@ public:
class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode class Q_QUICK_PRIVATE_EXPORT QSGImageNode : public QSGVisitableNode
{ {
public: 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 setTargetRect(const QRectF &rect) = 0;
virtual void setInnerTargetRect(const QRectF &rect) = 0; virtual void setInnerTargetRect(const QRectF &rect) = 0;
virtual void setInnerSourceRect(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 setFiltering(QSGTexture::Filtering filtering) = 0;
virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0; virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0; virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) = 0;
virtual void setAntialiasing(AntialiasingFlags flags) { Q_UNUSED(flags); }
virtual void update() = 0; virtual void update() = 0;

View File

@ -140,11 +140,10 @@ void SmoothTextureMaterialShader::initialize()
QSGDefaultImageNode::QSGDefaultImageNode() QSGDefaultImageNode::QSGDefaultImageNode()
: m_innerSourceRect(0, 0, 1, 1) : m_innerSourceRect(0, 0, 1, 1)
, m_subSourceRect(0, 0, 1, 1) , m_subSourceRect(0, 0, 1, 1)
, m_antialiasing(false)
, m_mirror(false) , m_mirror(false)
, m_dirtyGeometry(false) , m_dirtyGeometry(false)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
, m_antialiasing(AntialiasingNone)
{ {
setMaterial(&m_materialO); setMaterial(&m_materialO);
setOpaqueMaterial(&m_material); setOpaqueMaterial(&m_material);
@ -250,20 +249,10 @@ void QSGDefaultImageNode::setTexture(QSGTexture *texture)
void QSGDefaultImageNode::setAntialiasing(bool antialiasing) void QSGDefaultImageNode::setAntialiasing(bool antialiasing)
{ {
AntialiasingFlags antialiasingFlags = antialiasing if (antialiasing == m_antialiasing)
? AntialiasingAll
: AntialiasingNone;
setAntialiasing(antialiasingFlags);
}
void QSGDefaultImageNode::setAntialiasing(AntialiasingFlags antialiasingFlags)
{
if (antialiasingFlags == m_antialiasing)
return; return;
m_antialiasing = antialiasing;
m_antialiasing = antialiasingFlags; if (m_antialiasing) {
if (m_antialiasing != AntialiasingNone) {
setMaterial(&m_smoothMaterial); setMaterial(&m_smoothMaterial);
setOpaqueMaterial(0); setOpaqueMaterial(0);
setGeometry(new QSGGeometry(smoothAttributeSet(), 0)); setGeometry(new QSGGeometry(smoothAttributeSet(), 0));
@ -375,14 +364,11 @@ void QSGDefaultImageNode::updateGeometry()
} }
// An image can be rendered as a single quad if: // An image can be rendered as a single quad if:
// - There is antialiasing on all or no edges
// - There are no margins, and either: // - There are no margins, and either:
// - the image isn't repeated // - the image isn't repeated
// - the source rectangle fills the entire texture so that texture wrapping can be used, // - the source rectangle fills the entire texture so that texture wrapping can be used,
// and NPOT is supported // and NPOT is supported
if (!hasMargins if (!hasMargins && (!hasTiles || (fullTexture && wrapSupported))) {
&& (m_antialiasing == AntialiasingAll || m_antialiasing == AntialiasingNone)
&& (!hasTiles || (fullTexture && wrapSupported))) {
QRectF sr; QRectF sr;
if (!fullTexture) { if (!fullTexture) {
sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(), sr = QRectF(innerSourceRect.x() + (m_subSourceRect.left() - floorLeft) * innerSourceRect.width(),
@ -561,35 +547,10 @@ void QSGDefaultImageNode::updateGeometry()
topDv = bottomDv *= 0.5f; 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. // This delta is how much the fuzziness can reach out from the image.
float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height()) float delta = float(qAbs(m_targetRect.width()) < qAbs(m_targetRect.height())
? m_targetRect.width() : m_targetRect.height()) * 0.5f; ? 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; quint16 index = 0;
ys = yData.data(); ys = yData.data();
for (int j = 0; j < vCells; ++j, ys += 2) { for (int j = 0; j < vCells; ++j, ys += 2) {
@ -639,28 +600,28 @@ void QSGDefaultImageNode::updateGeometry()
if (isTop) { if (isTop) {
vertices[topLeft].dy = vertices[topRight].dy = topDy; vertices[topLeft].dy = vertices[topRight].dy = topDy;
vertices[topLeft].dv = vertices[topRight].dv = topDv; 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); appendQuad(&indices, topLeft + 1, topRight + 1, topLeft, topRight);
} }
if (isBottom) { if (isBottom) {
vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy; vertices[bottomLeft].dy = vertices[bottomRight].dy = -bottomDy;
vertices[bottomLeft].dv = vertices[bottomRight].dv = -bottomDv; 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); appendQuad(&indices, bottomLeft, bottomRight, bottomLeft + 1, bottomRight + 1);
} }
if (isLeft) { if (isLeft) {
vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx; vertices[topLeft].dx = vertices[bottomLeft].dx = leftDx;
vertices[topLeft].du = vertices[bottomLeft].du = leftDu; 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); appendQuad(&indices, topLeft + 1, topLeft, bottomLeft + 1, bottomLeft);
} }
if (isRight) { if (isRight) {
vertices[topRight].dx = vertices[bottomRight].dx = -rightDx; vertices[topRight].dx = vertices[bottomRight].dx = -rightDx;
vertices[topRight].du = vertices[bottomRight].du = -rightDu; 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); appendQuad(&indices, topRight, topRight + 1, bottomRight, bottomRight + 1);
} }
} }

View File

@ -62,7 +62,6 @@ public:
virtual void setSubSourceRect(const QRectF &rect); virtual void setSubSourceRect(const QRectF &rect);
virtual void setTexture(QSGTexture *t); virtual void setTexture(QSGTexture *t);
virtual void setAntialiasing(bool antialiasing); virtual void setAntialiasing(bool antialiasing);
virtual void setAntialiasing(AntialiasingFlags antialiasing);
virtual void setMirror(bool mirror); virtual void setMirror(bool mirror);
virtual void update(); virtual void update();
@ -85,11 +84,11 @@ private:
QSGTextureMaterial m_materialO; QSGTextureMaterial m_materialO;
QSGSmoothTextureMaterial m_smoothMaterial; QSGSmoothTextureMaterial m_smoothMaterial;
uint m_antialiasing : 1;
uint m_mirror : 1; uint m_mirror : 1;
uint m_dirtyGeometry : 1; uint m_dirtyGeometry : 1;
QSGGeometry m_geometry; QSGGeometry m_geometry;
AntialiasingFlags m_antialiasing;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -38,6 +38,7 @@
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <QtGui/QOffscreenSurface>
#include <QtQuick/private/qsgcontext_p.h> #include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/private/qquickwindow_p.h> #include <QtQuick/private/qquickwindow_p.h>
@ -210,15 +211,29 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
hide(window); hide(window);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
if (m_gl) bool current = false;
m_gl->makeCurrent(window); 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(); d->cleanupNodesOnShutdown();
if (m_windows.size() == 0) { if (m_windows.size() == 0) {
d->context->invalidate(); d->context->invalidate();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete m_gl; delete m_gl;
m_gl = 0; m_gl = 0;
} else if (m_gl) { } else if (m_gl && current) {
m_gl->doneCurrent(); m_gl->doneCurrent();
} }
} }

View File

@ -494,6 +494,7 @@ int main(int argc, char *argv[])
foreach (const QString &path, files) { foreach (const QString &path, files) {
//QUrl::fromUserInput doesn't treat no scheme as relative file paths //QUrl::fromUserInput doesn't treat no scheme as relative file paths
#ifndef QT_NO_REGULAREXPRESSION
QRegularExpression urlRe("[[:word:]]+://.*"); QRegularExpression urlRe("[[:word:]]+://.*");
if (urlRe.match(path).hasMatch()) { //Treat as a URL if (urlRe.match(path).hasMatch()) { //Treat as a URL
QUrl url = QUrl::fromUserInput(path); QUrl url = QUrl::fromUserInput(path);
@ -503,7 +504,9 @@ int main(int argc, char *argv[])
? QDir::toNativeSeparators(url.toLocalFile()) ? QDir::toNativeSeparators(url.toLocalFile())
: url.toString())); : url.toString()));
e.load(url); e.load(url);
} else { //Local file path } else
#endif
{ //Local file path
if (verboseMode) if (verboseMode)
printf("qml: loading %s\n", qPrintable(QDir::toNativeSeparators(path))); printf("qml: loading %s\n", qPrintable(QDir::toNativeSeparators(path)));