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
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
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}

View File

@ -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

View File

@ -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 (updatePixmap)
node->setTexture(texture);
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;
}
}
// 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()));
}
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;
}
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);
}
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;
}
}
node->setTargetRect(targetRect);
node->setInnerSourceRect(innerSourceRect);
node->setInnerTargetRect(innerTargetRect);
node->setSubSourceRect(QRectF(0, 0, hTiles, vTiles));
node->setMirror(d->mirror);
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);
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();
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 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();
}
}
return oldNode;
return node;
}
void QQuickBorderImage::pixmapChange()

View File

@ -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)
};

View File

@ -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;
};

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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)));