Merge remote-tracking branch 'origin/5.12' into 5.13

Change-Id: I47735445e4d31ba47d596d964b3f050e263bd1d9
This commit is contained in:
Qt Forward Merge Bot 2019-07-05 01:00:04 +02:00
commit 6af8e21bb0
9 changed files with 86 additions and 25 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,4 @@
import QtQml 2.12
import "qrc:/"
QtObject {}

View File

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

View File

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