diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-07-05 01:00:04 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-07-05 01:00:13 +0200 |
commit | 6063dd35b8dca1f6ca40f0133a5f21c1c2179316 (patch) | |
tree | 562427d956f4aac33a8555ae4526b85cd59ef473 | |
parent | 47b2cde5dcca49a1969a43b294931323eff68f74 (diff) | |
parent | 6af8e21bb0555623647631ed9be1982335b77534 (diff) |
Merge "Merge remote-tracking branch 'origin/5.12' into 5.13"
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 6 | ||||
-rw-r--r-- | src/qml/util/qqmladaptormodel.cpp | 10 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp | 40 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h | 9 | ||||
-rw-r--r-- | tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 12 | ||||
-rw-r--r-- | tests/auto/qml/qqmltypeloader/data/qrcRootPath.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp | 8 | ||||
-rw-r--r-- | tools/qmlcachegen/qtquickcompiler.prf | 10 |
9 files changed, 86 insertions, 25 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index a23a322df9..7ad9310160 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -571,6 +571,12 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url) { Q_D(QQmlComponent); + if (!d->engine) { + // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check + qWarning("QQmlComponent: Must provide an engine before calling setData"); + return; + } + d->clear(); d->url = url; @@ -777,6 +783,12 @@ QObject *QQmlComponent::create(QQmlContext *context) Q_D(QQmlComponent); QML_MEMORY_SCOPE_URL(url()); + if (!d->engine) { + // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check + qWarning("QQmlComponent: Must provide an engine before calling create"); + return nullptr; + } + if (!context) context = d->engine->rootContext(); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 457558fb56..5d3b1cedc5 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1495,7 +1495,11 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL bool incomplete = false; - QUrl qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir"))); + QUrl importUrl(importUri); + QString path = importUrl.path(); + path.append(QLatin1String(path.endsWith(QLatin1Char('/')) ? "qmldir" : "/qmldir")); + importUrl.setPath(path); + QUrl qmldirUrl = finalUrl().resolved(importUrl); if (!QQmlImports::isLocal(qmldirUrl)) { // This is a remote file; the import is currently incomplete incomplete = true; diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index a9a38c5381..1ff866eb74 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -162,8 +162,14 @@ public: signalIndexes.append(propertyId + signalOffset); } - for (int i = 0, c = items.count(); i < c; ++i) { - QQmlDelegateModelItem *item = items.at(i); + QVarLengthArray<QQmlGuard<QQmlDelegateModelItem>> guardedItems; + for (const auto item : items) + guardedItems.append(item); + + for (const auto &item : qAsConst(guardedItems)) { + if (item.isNull()) + continue; + const int idx = item->modelIndex(); if (idx >= index && idx < index + count) { for (int i = 0; i < signalIndexes.count(); ++i) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 8121b4559e..c51358df7c 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -68,7 +68,8 @@ DEFINE_BOOL_CONFIG_OPTION(qsgPreferFullSizeGlyphCacheTextures, QSG_PREFER_FULLSI QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QOpenGLContext *c, const QRawFont &font) : QSGDistanceFieldGlyphCache(font) - , m_maxTextureSize(0) + , m_maxTextureWidth(0) + , m_maxTextureHeight(0) , m_maxTextureCount(3) , m_areaAllocator(nullptr) , m_blitProgram(nullptr) @@ -112,13 +113,23 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph QList<GlyphPosition> glyphPositions; QVector<glyph_t> glyphsToRender; + const int padding = QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING; + const qreal scaleFactor = qreal(1) / QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution); + + if (m_maxTextureHeight == 0) { + m_funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureWidth); + + // We need to add a buffer to avoid glyphs that overlap the border between two + // textures causing the height of the textures to extend beyond the limit. + m_maxTextureHeight = m_maxTextureWidth - (qCeil(m_referenceFont.pixelSize() * scaleFactor) + distanceFieldRadius() * 2 + padding * 2); + } + if (m_areaAllocator == nullptr) - m_areaAllocator = new QSGAreaAllocator(QSize(maxTextureSize(), m_maxTextureCount * maxTextureSize())); + m_areaAllocator = new QSGAreaAllocator(QSize(m_maxTextureWidth, m_maxTextureCount * m_maxTextureHeight)); for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) { glyph_t glyphIndex = *it; - int padding = QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING; QRectF boundingRect = glyphData(glyphIndex).boundingRect; int glyphWidth = qCeil(boundingRect.width()) + distanceFieldRadius() * 2; int glyphHeight = qCeil(boundingRect.height()) + distanceFieldRadius() * 2; @@ -151,8 +162,8 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph continue; } - TextureInfo *tex = textureInfo(alloc.y() / maxTextureSize()); - alloc = QRect(alloc.x(), alloc.y() % maxTextureSize(), alloc.width(), alloc.height()); + TextureInfo *tex = textureInfo(alloc.y() / m_maxTextureHeight); + alloc = QRect(alloc.x(), alloc.y() % m_maxTextureHeight, alloc.width(), alloc.height()); tex->allocatedArea |= alloc; Q_ASSERT(tex->padding == padding || tex->padding < 0); @@ -539,13 +550,6 @@ bool QSGDefaultDistanceFieldGlyphCache::createFullSizeTextures() const return qsgPreferFullSizeGlyphCacheTextures() && glyphCount() > QT_DISTANCEFIELD_HIGHGLYPHCOUNT(); } -int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const -{ - if (!m_maxTextureSize) - m_funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); - return m_maxTextureSize; -} - namespace { struct Qtdf { // We need these structs to be tightly packed, but some compilers we use do not @@ -644,7 +648,7 @@ bool QSGDefaultDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &fo } qreal pixelSize = qreal(Qtdf::fetch<quint16>(qtdfTableStart, Qtdf::pixelSize)); - m_maxTextureSize = Qtdf::fetch<quint32>(qtdfTableStart, Qtdf::textureSize); + m_maxTextureWidth = m_maxTextureHeight = Qtdf::fetch<quint32>(qtdfTableStart, Qtdf::textureSize); m_doubleGlyphResolution = Qtdf::fetch<quint8>(qtdfTableStart, Qtdf::flags) == 1; padding = Qtdf::fetch<quint8>(qtdfTableStart, Qtdf::headerPadding); @@ -653,7 +657,7 @@ bool QSGDefaultDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &fo return false; } - if (m_maxTextureSize <= 0) { + if (m_maxTextureWidth <= 0) { qWarning("Invalid texture size in '%s'", qPrintable(font.familyName())); return false; } @@ -661,11 +665,11 @@ bool QSGDefaultDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &fo int systemMaxTextureSize; m_funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &systemMaxTextureSize); - if (m_maxTextureSize > systemMaxTextureSize) { + if (m_maxTextureWidth > systemMaxTextureSize) { qWarning("System maximum texture size is %d. This is lower than the value in '%s', which is %d", systemMaxTextureSize, qPrintable(font.familyName()), - m_maxTextureSize); + m_maxTextureWidth); } if (padding != QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING) { @@ -688,12 +692,12 @@ bool QSGDefaultDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &fo return false; } - if (m_areaAllocator->size().height() % m_maxTextureSize != 0) { + if (m_areaAllocator->size().height() % m_maxTextureHeight != 0) { qWarning("Area allocator size mismatch in '%s'", qPrintable(font.familyName())); return false; } - textureCount = m_areaAllocator->size().height() / m_maxTextureSize; + textureCount = m_areaAllocator->size().height() / m_maxTextureHeight; m_maxTextureCount = qMax(m_maxTextureCount, textureCount); const char *textureRecord = allocatorData; diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index c64adddd91..0420ef251e 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -80,7 +80,6 @@ public: bool useTextureResizeWorkaround() const; bool useTextureUploadWorkaround() const; bool createFullSizeTextures() const; - int maxTextureSize() const; void setMaxTextureCount(int max) { m_maxTextureCount = max; } int maxTextureCount() const { return m_maxTextureCount; } @@ -97,7 +96,7 @@ private: QDistanceField image; int padding = -1; - TextureInfo(const QRect &preallocRect = QRect()) : texture(0), allocatedArea(preallocRect) { } + TextureInfo(const QRect &preallocRect = QRect(0, 0, 1, 1)) : texture(0), allocatedArea(preallocRect) { } }; void createTexture(TextureInfo * texInfo, int width, int height, const void *pixels); @@ -106,9 +105,10 @@ private: TextureInfo *textureInfo(int index) { + Q_ASSERT(m_maxTextureWidth > 0 && m_maxTextureHeight > 0); for (int i = m_textures.count(); i <= index; ++i) { if (createFullSizeTextures()) - m_textures.append(QRect(0, 0, maxTextureSize(), maxTextureSize())); + m_textures.append(QRect(0, 0, m_maxTextureWidth, m_maxTextureWidth)); else m_textures.append(TextureInfo()); } @@ -136,7 +136,8 @@ private: m_blitProgram->link(); } - mutable int m_maxTextureSize; + int m_maxTextureWidth; + int m_maxTextureHeight; int m_maxTextureCount; bool m_coreProfile; diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 7c7c7d3bd0..a872cece96 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -121,6 +121,7 @@ private slots: void setNonExistentInitialProperty(); void relativeUrl_data(); void relativeUrl(); + void setDataNoEngineNoSegfault(); private: QQmlEngine engine; @@ -654,6 +655,17 @@ void tst_qqmlcomponent::relativeUrl() QVERIFY2(!component.isError(), qPrintable(component.errorString())); } +void tst_qqmlcomponent::setDataNoEngineNoSegfault() +{ + QQmlEngine eng; + QQmlComponent comp; + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Must provide an engine before calling setData"); + comp.setData("import QtQuick 1.0; QtObject { }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Must provide an engine before calling create"); + auto c = comp.create(); + QVERIFY(!c); +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" diff --git a/tests/auto/qml/qqmltypeloader/data/qrcRootPath.qml b/tests/auto/qml/qqmltypeloader/data/qrcRootPath.qml new file mode 100644 index 0000000000..bdbee4eb59 --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/qrcRootPath.qml @@ -0,0 +1,4 @@ +import QtQml 2.12 +import "qrc:/" + +QtObject {} diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 0c4abf19f4..52c722aac8 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -56,6 +56,7 @@ private slots: void qmlSingletonWithinModule(); void multiSingletonModule(); void implicitComponentModule(); + void qrcRootPathUrl(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -503,6 +504,13 @@ void tst_QQMLTypeLoader::implicitComponentModule() checkCleanCacheLoad(QLatin1String("implicitComponentModule")); } +void tst_QQMLTypeLoader::qrcRootPathUrl() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("qrcRootPath.qml")); + QCOMPARE(component.status(), QQmlComponent::Ready); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tools/qmlcachegen/qtquickcompiler.prf b/tools/qmlcachegen/qtquickcompiler.prf index 2f98aadefe..24cbe7f2e5 100644 --- a/tools/qmlcachegen/qtquickcompiler.prf +++ b/tools/qmlcachegen/qtquickcompiler.prf @@ -1,5 +1,15 @@ if(qtc_run|lupdate_run): return() +!contains(QT, qml) { + qt_modules = \ + $$replace(QT, -private$, _private) \ + $$replace(QT_PRIVATE, -private$, _private) + qt_modules = $$resolve_depends(qt_modules, "QT.", ".depends" ".run_depends") + !contains(qt_modules, qml): \ + error("The qtquickcompiler feature cannot be used without the QML module.") + unset(qt_modules) +} + qtPrepareTool(QML_CACHEGEN, qmlcachegen, _FILTER) qtPrepareTool(QMAKE_RCC, rcc, _DEP) |