diff options
-rw-r--r-- | src/core/aspects/qaspectengine.cpp | 2 | ||||
-rw-r--r-- | src/core/nodes/qnode_p.h | 2 | ||||
-rw-r--r-- | src/core/qscene.cpp | 14 | ||||
-rw-r--r-- | src/core/qscene_p.h | 5 | ||||
-rw-r--r-- | src/extras/text/distancefieldtextrenderer_p_p.h | 1 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldglyphcache.cpp | 100 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldglyphcache.h | 90 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldglyphcache_p.h | 87 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldtext.cpp | 82 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldtext.h | 5 | ||||
-rw-r--r-- | src/extras/text/qdistancefieldtext_p.h | 19 | ||||
-rw-r--r-- | src/extras/text/qtextureatlas.cpp | 2 | ||||
-rw-r--r-- | src/extras/text/qtextureatlas.h | 84 | ||||
-rw-r--r-- | src/extras/text/qtextureatlas_p.h | 82 | ||||
-rw-r--r-- | src/extras/text/qtextureatlas_p_p.h | 139 | ||||
-rw-r--r-- | src/extras/text/text.pri | 9 | ||||
-rw-r--r-- | src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp | 3 | ||||
-rw-r--r-- | tests/manual/distancefieldtext/TextScene.qml | 5 |
18 files changed, 361 insertions, 370 deletions
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index 15f975332..c1ec1b4ac 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -218,6 +218,8 @@ QAspectEngine::~QAspectEngine() void QAspectEnginePrivate::initNodeTree(QNode *node) { + // Set the root entity on the scene + m_scene->setRootNode(node); QNodeVisitor visitor; visitor.traverse(node, this, &QAspectEnginePrivate::initNode, &QAspectEnginePrivate::initEntity); } diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index 5d6329e62..d4a48aa1e 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -74,7 +74,7 @@ public: void init(QNode *parent); - void setScene(QScene *scene); + virtual void setScene(QScene *scene); QScene *scene() const; void setArbiter(QLockableObserverInterface *arbiter) Q_DECL_OVERRIDE; diff --git a/src/core/qscene.cpp b/src/core/qscene.cpp index 972659131..1fcfeaac7 100644 --- a/src/core/qscene.cpp +++ b/src/core/qscene.cpp @@ -55,6 +55,7 @@ public: QScenePrivate(QAspectEngine *engine) : m_engine(engine) , m_arbiter(nullptr) + , m_rootNode(nullptr) { } @@ -67,6 +68,7 @@ public: QLockableObserverInterface *m_arbiter; mutable QReadWriteLock m_lock; mutable QReadWriteLock m_nodePropertyTrackModeLock; + QNode *m_rootNode; }; @@ -171,6 +173,12 @@ QNodeId QScene::nodeIdFromObservable(QObservableInterface *observable) const return d->m_observableToUuid.value(observable); } +QNode *QScene::rootNode() const +{ + Q_D(const QScene); + return d->m_rootNode; +} + void QScene::setArbiter(QLockableObserverInterface *arbiter) { Q_D(QScene); @@ -236,6 +244,12 @@ void QScene::removePropertyTrackDataForNode(QNodeId nodeId) d->m_nodePropertyTrackModeLookupTable.remove(nodeId); } +void QScene::setRootNode(QNode *root) +{ + Q_D(QScene); + d->m_rootNode = root; +} + } // Qt3D QT_END_NAMESPACE diff --git a/src/core/qscene_p.h b/src/core/qscene_p.h index 1a313c249..fdcb23edb 100644 --- a/src/core/qscene_p.h +++ b/src/core/qscene_p.h @@ -83,6 +83,8 @@ public: QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const; QNodeId nodeIdFromObservable(QObservableInterface *observable) const; + QNode *rootNode() const; + void setArbiter(Qt3DCore::QLockableObserverInterface *arbiter); Qt3DCore::QLockableObserverInterface *arbiter() const; @@ -105,6 +107,9 @@ public: private: Q_DECLARE_PRIVATE(QScene) QScopedPointer<QScenePrivate> d_ptr; + + void setRootNode(QNode *root); + friend class QAspectEnginePrivate; }; } // Qt3D diff --git a/src/extras/text/distancefieldtextrenderer_p_p.h b/src/extras/text/distancefieldtextrenderer_p_p.h index fd2e76167..06c377a35 100644 --- a/src/extras/text/distancefieldtextrenderer_p_p.h +++ b/src/extras/text/distancefieldtextrenderer_p_p.h @@ -52,7 +52,6 @@ // #include <Qt3DCore/private/qentity_p.h> -#include <Qt3DExtras/qdistancefieldglyphcache.h> #include <Qt3DExtras/private/distancefieldtextrenderer_p.h> QT_BEGIN_NAMESPACE diff --git a/src/extras/text/qdistancefieldglyphcache.cpp b/src/extras/text/qdistancefieldglyphcache.cpp index dfe59883c..aacccc7dc 100644 --- a/src/extras/text/qdistancefieldglyphcache.cpp +++ b/src/extras/text/qdistancefieldglyphcache.cpp @@ -41,9 +41,13 @@ #include <QtGui/qglyphrun.h> #include <QtGui/private/qrawfont_p.h> -#include "qdistancefieldglyphcache.h" #include "qdistancefieldglyphcache_p.h" -#include "qtextureatlas.h" +#include "qtextureatlas_p.h" + +#include <QtGui/qfont.h> +#include <QtGui/private/qdistancefield_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DExtras/private/qtextureatlas_p.h> QT_BEGIN_NAMESPACE @@ -53,6 +57,59 @@ using namespace Qt3DCore; namespace Qt3DExtras { +// ref-count glyphs and keep track of where they are stored +class StoredGlyph { +public: + StoredGlyph() = default; + StoredGlyph(const StoredGlyph &other) = default; + StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution); + + int refCount() const { return m_ref; } + void ref() { ++m_ref; } + int deref() { return m_ref = std::max(m_ref - 1, (quint32) 0); } + + bool addToTextureAtlas(QTextureAtlas *atlas); + void removeFromTextureAtlas(); + + QTextureAtlas *atlas() const { return m_atlas; } + QRectF glyphPathBoundingRect() const { return m_glyphPathBoundingRect; } + QRectF texCoords() const; + +private: + quint32 m_glyph = (quint32) -1; + quint32 m_ref = 0; + QTextureAtlas *m_atlas = nullptr; + QTextureAtlas::TextureId m_atlasEntry = QTextureAtlas::InvalidTexture; + QRectF m_glyphPathBoundingRect; + QImage m_distanceFieldImage; // only used until added to texture atlas +}; + +// A DistanceFieldFont stores all glyphs for a given QRawFont. +// it will use multiple QTextureAtlasess to store the distance +// fields and uses ref-counting for each glyph to ensure that +// unused glyphs are removed from the texture atlasses. +class DistanceFieldFont +{ +public: + DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent); + ~DistanceFieldFont(); + + StoredGlyph findGlyph(quint32 glyph) const; + StoredGlyph refGlyph(quint32 glyph); + void derefGlyph(quint32 glyph); + + bool doubleGlyphResolution() const { return m_doubleGlyphResolution; } + +private: + QRawFont m_font; + bool m_doubleGlyphResolution; + Qt3DCore::QNode *m_parentNode; // parent node for the QTextureAtlasses + + QHash<quint32, StoredGlyph> m_glyphs; + + QVector<QTextureAtlas*> m_atlasses; +}; + StoredGlyph::StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution) : m_glyph(glyph) , m_ref(1) @@ -190,7 +247,7 @@ void DistanceFieldFont::derefGlyph(quint32 glyph) // copied from QSGDistanceFieldGlyphCacheManager::fontKey // we use this function to compare QRawFonts, as QRawFont doesn't // implement a stable comparison function -QString QDistanceFieldGlyphCachePrivate::fontKey(const QRawFont &font) +QString QDistanceFieldGlyphCache::fontKey(const QRawFont &font) { QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine; if (!fe->faceId().filename.isEmpty()) { @@ -210,7 +267,7 @@ QString QDistanceFieldGlyphCachePrivate::fontKey(const QRawFont &font) } } -DistanceFieldFont* QDistanceFieldGlyphCachePrivate::getOrCreateDistanceFieldFont(const QRawFont &font) +DistanceFieldFont* QDistanceFieldGlyphCache::getOrCreateDistanceFieldFont(const QRawFont &font) { // return, if font already exists (make sure to only create one DistanceFieldFont for // each unique QRawFont, by building a hash on the QRawFont that ignores the font size) @@ -229,13 +286,13 @@ DistanceFieldFont* QDistanceFieldGlyphCachePrivate::getOrCreateDistanceFieldFont actualFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(useDoubleRes) * QT_DISTANCEFIELD_SCALE(useDoubleRes)); // create new font cache - DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, q_func()); + DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, m_rootNode); m_fonts.insert(key, dff); return dff; } -QDistanceFieldGlyphCache::QDistanceFieldGlyphCache(QNode *parent) - : QNode(*new QDistanceFieldGlyphCachePrivate(), parent) +QDistanceFieldGlyphCache::QDistanceFieldGlyphCache() + : m_rootNode(nullptr) { } @@ -243,10 +300,19 @@ QDistanceFieldGlyphCache::~QDistanceFieldGlyphCache() { } +void QDistanceFieldGlyphCache::setRootNode(QNode *rootNode) +{ + m_rootNode = rootNode; +} + +QNode *QDistanceFieldGlyphCache::rootNode() const +{ + return m_rootNode; +} + bool QDistanceFieldGlyphCache::doubleGlyphResolution(const QRawFont &font) { - Q_D(QDistanceFieldGlyphCache); - return d->getOrCreateDistanceFieldFont(font)->doubleGlyphResolution(); + return getOrCreateDistanceFieldFont(font)->doubleGlyphResolution(); } namespace { @@ -266,13 +332,11 @@ QDistanceFieldGlyphCache::Glyph refAndGetGlyph(DistanceFieldFont *dff, quint32 g return ret; } -} +} // anonymous QVector<QDistanceFieldGlyphCache::Glyph> QDistanceFieldGlyphCache::refGlyphs(const QGlyphRun &run) { - Q_D(QDistanceFieldGlyphCache); - - DistanceFieldFont *dff = d->getOrCreateDistanceFieldFont(run.rawFont()); + DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont()); QVector<QDistanceFieldGlyphCache::Glyph> ret; const QVector<quint32> glyphs = run.glyphIndexes(); @@ -284,15 +348,12 @@ QVector<QDistanceFieldGlyphCache::Glyph> QDistanceFieldGlyphCache::refGlyphs(con QDistanceFieldGlyphCache::Glyph QDistanceFieldGlyphCache::refGlyph(const QRawFont &font, quint32 glyph) { - Q_D(QDistanceFieldGlyphCache); - return refAndGetGlyph(d->getOrCreateDistanceFieldFont(font), glyph); + return refAndGetGlyph(getOrCreateDistanceFieldFont(font), glyph); } void QDistanceFieldGlyphCache::derefGlyphs(const QGlyphRun &run) { - Q_D(QDistanceFieldGlyphCache); - - DistanceFieldFont *dff = d->getOrCreateDistanceFieldFont(run.rawFont()); + DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont()); const QVector<quint32> glyphs = run.glyphIndexes(); for (quint32 glyph : glyphs) @@ -301,8 +362,7 @@ void QDistanceFieldGlyphCache::derefGlyphs(const QGlyphRun &run) void QDistanceFieldGlyphCache::derefGlyph(const QRawFont &font, quint32 glyph) { - Q_D(QDistanceFieldGlyphCache); - d->getOrCreateDistanceFieldFont(font)->derefGlyph(glyph); + getOrCreateDistanceFieldFont(font)->derefGlyph(glyph); } } // namespace Qt3DExtras diff --git a/src/extras/text/qdistancefieldglyphcache.h b/src/extras/text/qdistancefieldglyphcache.h deleted file mode 100644 index b02625b47..000000000 --- a/src/extras/text/qdistancefieldglyphcache.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_H -#define QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_H - -#include <QtCore/QRectF> -#include <Qt3DCore/qnode.h> -#include <Qt3DExtras/qt3dextras_global.h> - -QT_BEGIN_NAMESPACE - -class QRawFont; -class QGlyphRun; - -namespace Qt3DRender { -class QAbstractTexture; -} - -namespace Qt3DExtras { - -class QDistanceFieldGlyphCachePrivate; - -class QT3DEXTRASSHARED_EXPORT QDistanceFieldGlyphCache : public Qt3DCore::QNode -{ - Q_OBJECT - -public: - QDistanceFieldGlyphCache(Qt3DCore::QNode *parent = nullptr); - ~QDistanceFieldGlyphCache(); - - struct Glyph { - Qt3DRender::QAbstractTexture *texture = nullptr; - QRectF glyphPathBoundingRect; // bounding rect of the QPainterPath used to draw the glyph - QRectF texCoords; // texture coordinates within texture - }; - - bool doubleGlyphResolution(const QRawFont &font); - - QVector<Glyph> refGlyphs(const QGlyphRun &run); - Glyph refGlyph(const QRawFont &font, quint32 glyph); - - void derefGlyphs(const QGlyphRun &run); - void derefGlyph(const QRawFont &font, quint32 glyph); - -private: - Q_DECLARE_PRIVATE(QDistanceFieldGlyphCache) -}; - -} // namespace Qt3DExtras - -QT_END_NAMESPACE - -#endif // QT3DEXTRAS_QDISTANCEFIELDGLYPHCACHE_H diff --git a/src/extras/text/qdistancefieldglyphcache_p.h b/src/extras/text/qdistancefieldglyphcache_p.h index 90164cd39..6ca011c76 100644 --- a/src/extras/text/qdistancefieldglyphcache_p.h +++ b/src/extras/text/qdistancefieldglyphcache_p.h @@ -51,82 +51,57 @@ // We mean it. // -#include <QtCore/qscopedpointer.h> -#include <QtGui/qglyphrun.h> -#include <QtGui/qfont.h> -#include <QtGui/private/qdistancefield_p.h> -#include <Qt3DCore/private/qnode_p.h> -#include <Qt3DExtras/qdistancefieldglyphcache.h> -#include <Qt3DExtras/qtextureatlas.h> +#include <QtCore/QRectF> +#include <Qt3DCore/qnode.h> +#include <Qt3DExtras/qt3dextras_global.h> QT_BEGIN_NAMESPACE -namespace Qt3DExtras { +class QRawFont; +class QGlyphRun; -// ref-count glyphs and keep track of where they are stored -class StoredGlyph { -public: - StoredGlyph() = default; - StoredGlyph(const StoredGlyph &other) = default; - StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution); +namespace Qt3DCore { +class QNode; +} - int refCount() const { return m_ref; } - void ref() { ++m_ref; } - int deref() { return m_ref = std::max(m_ref - 1, (quint32) 0); } +namespace Qt3DRender { +class QAbstractTexture; +} - bool addToTextureAtlas(QTextureAtlas *atlas); - void removeFromTextureAtlas(); +namespace Qt3DExtras { - QTextureAtlas *atlas() const { return m_atlas; } - QRectF glyphPathBoundingRect() const { return m_glyphPathBoundingRect; } - QRectF texCoords() const; +class DistanceFieldFont; +class QDistanceFieldGlyphCachePrivate; -private: - quint32 m_glyph = (quint32) -1; - quint32 m_ref = 0; - QTextureAtlas *m_atlas = nullptr; - QTextureAtlas::TextureId m_atlasEntry = QTextureAtlas::InvalidTexture; - QRectF m_glyphPathBoundingRect; - QImage m_distanceFieldImage; // only used until added to texture atlas -}; - -// A DistanceFieldFont stores all glyphs for a given QRawFont. -// it will use multiple QTextureAtlasess to store the distance -// fields and uses ref-counting for each glyph to ensure that -// unused glyphs are removed from the texture atlasses. -class DistanceFieldFont +class QDistanceFieldGlyphCache { public: - DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent); - ~DistanceFieldFont(); - - StoredGlyph findGlyph(quint32 glyph) const; - StoredGlyph refGlyph(quint32 glyph); - void derefGlyph(quint32 glyph); + QDistanceFieldGlyphCache(); + ~QDistanceFieldGlyphCache(); - bool doubleGlyphResolution() const { return m_doubleGlyphResolution; } + void setRootNode(Qt3DCore::QNode *rootNode); + Qt3DCore::QNode *rootNode() const; -private: - QRawFont m_font; - bool m_doubleGlyphResolution; - Qt3DCore::QNode *m_parentNode; // parent node for the QTextureAtlasses + struct Glyph { + Qt3DRender::QAbstractTexture *texture = nullptr; + QRectF glyphPathBoundingRect; // bounding rect of the QPainterPath used to draw the glyph + QRectF texCoords; // texture coordinates within texture + }; - QHash<quint32, StoredGlyph> m_glyphs; + bool doubleGlyphResolution(const QRawFont &font); - QVector<QTextureAtlas*> m_atlasses; -}; + QVector<Glyph> refGlyphs(const QGlyphRun &run); + Glyph refGlyph(const QRawFont &font, quint32 glyph); -class QDistanceFieldGlyphCachePrivate : public Qt3DCore::QNodePrivate -{ -public: - Q_DECLARE_PUBLIC(QDistanceFieldGlyphCache) - - DistanceFieldFont* getOrCreateDistanceFieldFont(const QRawFont &font); + void derefGlyphs(const QGlyphRun &run); + void derefGlyph(const QRawFont &font, quint32 glyph); private: + DistanceFieldFont* getOrCreateDistanceFieldFont(const QRawFont &font); static QString fontKey(const QRawFont &font); QHash<QString, DistanceFieldFont*> m_fonts; + Qt3DCore::QNode *m_rootNode; }; } // namespace Qt3DExtras diff --git a/src/extras/text/qdistancefieldtext.cpp b/src/extras/text/qdistancefieldtext.cpp index fdd40fc5a..88e6e9be5 100644 --- a/src/extras/text/qdistancefieldtext.cpp +++ b/src/extras/text/qdistancefieldtext.cpp @@ -54,6 +54,8 @@ #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DCore/private/qscene_p.h> + QT_BEGIN_NAMESPACE namespace { @@ -67,8 +69,11 @@ inline Q_DECL_CONSTEXPR QRectF scaleRectF(const QRectF &rect, float scale) namespace Qt3DExtras { +QHash<Qt3DCore::QScene *, QDistanceFieldTextPrivate::CacheEntry> QDistanceFieldTextPrivate::m_glyphCacheInstances; + QDistanceFieldTextPrivate::QDistanceFieldTextPrivate() - : m_font(QLatin1String("Times"), 10) + : m_glyphCache(nullptr) + , m_font(QLatin1String("Times"), 10) , m_scaledFont(QLatin1String("Times"), 10) , m_color(QColor(255, 255, 255, 255)) { @@ -78,6 +83,38 @@ QDistanceFieldTextPrivate::~QDistanceFieldTextPrivate() { } +void QDistanceFieldTextPrivate::setScene(Qt3DCore::QScene *scene) +{ + if (scene == m_scene) + return; + + // Unref old glyph cache if it exists + if (m_scene != nullptr) { + m_glyphCache = nullptr; + QDistanceFieldTextPrivate::CacheEntry &entry = QDistanceFieldTextPrivate::m_glyphCacheInstances[m_scene]; + --entry.count; + if (entry.count == 0 && entry.glyphCache != nullptr) { + delete entry.glyphCache; + entry.glyphCache = nullptr; + } + } + + QEntityPrivate::setScene(scene); + + // Ref new glyph cache is scene is valid + if (scene != nullptr) { + QDistanceFieldTextPrivate::CacheEntry &entry = QDistanceFieldTextPrivate::m_glyphCacheInstances[scene]; + if (entry.glyphCache == nullptr) { + entry.glyphCache = new QDistanceFieldGlyphCache(); + entry.glyphCache->setRootNode(scene->rootNode()); + } + m_glyphCache = entry.glyphCache; + ++entry.count; + // Update to populate glyphCache if needed + update(); + } +} + QDistanceFieldText::QDistanceFieldText(QNode *parent) : Qt3DCore::QEntity(*new QDistanceFieldTextPrivate(), parent) { @@ -104,7 +141,8 @@ struct RenderData { void QDistanceFieldTextPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &runs) { - Q_ASSERT(m_glyphCache || runs.isEmpty()); + if (runs.isEmpty()) + return; // For each distinct texture, we need a separate DistanceFieldTextRenderer, // for which we need vertex and index data @@ -198,19 +236,20 @@ void QDistanceFieldTextPrivate::setCurrentGlyphRuns(const QVector<QGlyphRun> &ru } // de-ref all glyphs for previous QGlyphRuns - if (m_glyphCache) { - for (int i = 0; i < m_currentGlyphRuns.size(); i++) - m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]); - } + for (int i = 0; i < m_currentGlyphRuns.size(); i++) + m_glyphCache->derefGlyphs(m_currentGlyphRuns[i]); m_currentGlyphRuns = runs; } void QDistanceFieldTextPrivate::update() { + if (m_glyphCache == nullptr) + return; + QVector<QGlyphRun> glyphRuns; // collect all GlyphRuns generated by the QTextLayout - if (m_glyphCache && !m_position.isEmpty() && !m_text.isEmpty() && m_fontScale > 0.f) { + if (!m_position.isEmpty() && !m_text.isEmpty() && m_fontScale > 0.f) { QTextLayout layout(m_text, m_scaledFont); const float lineWidth = m_position.width() / computeActualScale(); float height = 0; @@ -257,7 +296,7 @@ void QDistanceFieldText::setFont(const QFont &font) emit fontChanged(font); - if (!d->m_text.isEmpty() && d->m_glyphCache) + if (!d->m_text.isEmpty()) d->update(); } } @@ -294,8 +333,7 @@ void QDistanceFieldText::setText(const QString &text) d->m_text = text; emit textChanged(text); - if (d->m_glyphCache) - d->update(); + d->update(); } } @@ -312,7 +350,7 @@ void QDistanceFieldText::setPosition(const QRectF &pos) d->m_position = pos; emit positionChanged(pos); - if (!d->m_text.isEmpty() && d->m_glyphCache) + if (!d->m_text.isEmpty()) d->update(); } } @@ -330,28 +368,6 @@ void QDistanceFieldText::setFontScale(float scale) d->m_fontScale = scale; emit fontScaleChanged(scale); - if (!d->m_text.isEmpty() && d->m_glyphCache) - d->update(); - } -} - -QDistanceFieldGlyphCache *QDistanceFieldText::glyphCache() const -{ - Q_D(const QDistanceFieldText); - return d->m_glyphCache; -} - -void QDistanceFieldText::setGlyphCache(QDistanceFieldGlyphCache *glyphCache) -{ - Q_D(QDistanceFieldText); - if (d->m_glyphCache != glyphCache) { - // make sure all glyphs that we still reference in our old glyph cache - // will be de-reffed - d->setCurrentGlyphRuns(QVector<QGlyphRun>()); - - d->m_glyphCache = glyphCache; - emit glyphCacheChanged(glyphCache); - if (!d->m_text.isEmpty()) d->update(); } diff --git a/src/extras/text/qdistancefieldtext.h b/src/extras/text/qdistancefieldtext.h index 2eaafda63..a1bfc9d9e 100644 --- a/src/extras/text/qdistancefieldtext.h +++ b/src/extras/text/qdistancefieldtext.h @@ -61,7 +61,6 @@ class QT3DEXTRASSHARED_EXPORT QDistanceFieldText : public Qt3DCore::QEntity Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(QRectF position READ position WRITE setPosition NOTIFY positionChanged) Q_PROPERTY(float fontScale READ fontScale WRITE setFontScale NOTIFY fontScaleChanged) - Q_PROPERTY(Qt3DExtras::QDistanceFieldGlyphCache* glyphCache READ glyphCache WRITE setGlyphCache NOTIFY glyphCacheChanged) public: explicit QDistanceFieldText(Qt3DCore::QNode *parent = nullptr); @@ -82,16 +81,12 @@ public: float fontScale() const; void setFontScale(float scale); - QDistanceFieldGlyphCache *glyphCache() const; - void setGlyphCache(QDistanceFieldGlyphCache *glyphCache); - Q_SIGNALS: void fontChanged(const QFont &font); void colorChanged(const QColor &color); void textChanged(const QString &text); void positionChanged(const QRectF &position); void fontScaleChanged(float scale); - void glyphCacheChanged(QDistanceFieldGlyphCache *glyphCache); private: Q_DECLARE_PRIVATE(QDistanceFieldText) diff --git a/src/extras/text/qdistancefieldtext_p.h b/src/extras/text/qdistancefieldtext_p.h index 578ed7f98..d30f226d6 100644 --- a/src/extras/text/qdistancefieldtext_p.h +++ b/src/extras/text/qdistancefieldtext_p.h @@ -52,12 +52,16 @@ // #include <Qt3DCore/private/qentity_p.h> -#include <Qt3DExtras/qdistancefieldglyphcache.h> #include <Qt3DExtras/private/distancefieldtextrenderer_p.h> +#include <Qt3DExtras/private/qdistancefieldglyphcache_p.h> #include <QFont> QT_BEGIN_NAMESPACE +namespace Qt3DCore { +class QScene; +} + namespace Qt3DRender { class QGeometryRenderer; class QGeometry; @@ -79,12 +83,13 @@ public: Q_DECLARE_PUBLIC(QDistanceFieldText) - QDistanceFieldGlyphCache *m_glyphCache = nullptr; - // keep track of the glyphs currently being displayed, // to guarantee proper glyph ref-counting in the // QDistanceFieldGlyphCache QVector<QGlyphRun> m_currentGlyphRuns; + QDistanceFieldGlyphCache *m_glyphCache; + + void setScene(Qt3DCore::QScene *scene) Q_DECL_OVERRIDE; QFont m_font; QFont m_scaledFont; // ignore point or pixel size, set to default value @@ -100,6 +105,14 @@ public: void setCurrentGlyphRuns(const QVector<QGlyphRun> &runs); void update(); + + struct CacheEntry + { + QDistanceFieldGlyphCache *glyphCache = nullptr; + int count = 0; + }; + + static QHash<Qt3DCore::QScene *, CacheEntry> m_glyphCacheInstances; }; } // namespace Qt3DExtras diff --git a/src/extras/text/qtextureatlas.cpp b/src/extras/text/qtextureatlas.cpp index 1a076a3ab..49c6397d6 100644 --- a/src/extras/text/qtextureatlas.cpp +++ b/src/extras/text/qtextureatlas.cpp @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#include "qtextureatlas.h" #include "qtextureatlas_p.h" +#include "qtextureatlas_p_p.h" #include <Qt3DRender/qtexturedata.h> #include <Qt3DRender/qabstracttextureimage.h> #include <Qt3DCore/qpropertyupdatedchange.h> diff --git a/src/extras/text/qtextureatlas.h b/src/extras/text/qtextureatlas.h deleted file mode 100644 index c70f9dfd3..000000000 --- a/src/extras/text/qtextureatlas.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DEXTRAS_QTEXTUREATLAS_H -#define QT3DEXTRAS_QTEXTUREATLAS_H - -#include <Qt3DExtras/qt3dextras_global.h> -#include <Qt3DRender/qabstracttexture.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DExtras { - -class QTextureAtlasPrivate; - -class QT3DEXTRASSHARED_EXPORT QTextureAtlas : public Qt3DRender::QAbstractTexture -{ - Q_OBJECT - -public: - typedef int TextureId; - static Q_CONSTEXPR TextureId InvalidTexture = -1; - - QTextureAtlas(Qt3DCore::QNode *parent = nullptr); - ~QTextureAtlas(); - - QOpenGLTexture::PixelFormat pixelFormat() const; - void setPixelFormat(QOpenGLTexture::PixelFormat fmt); - - TextureId addImage(const QImage &image, int padding); - void removeImage(TextureId id); - - int imageCount() const; - - bool hasImage(TextureId id) const; - QRect imagePosition(TextureId id) const; - QRectF imageTexCoords(TextureId id) const; - int imagePadding(TextureId id) const; - -private: - Q_DECLARE_PRIVATE(QTextureAtlas) -}; - -} // namespace Qt3DExtras - -QT_END_NAMESPACE - -#endif // QT3DEXTRAS_QTEXTUREATLAS_H diff --git a/src/extras/text/qtextureatlas_p.h b/src/extras/text/qtextureatlas_p.h index 34386a87a..8dc9e19b3 100644 --- a/src/extras/text/qtextureatlas_p.h +++ b/src/extras/text/qtextureatlas_p.h @@ -51,86 +51,42 @@ // We mean it. // -#include <QtCore/qscopedpointer.h> -#include <Qt3DRender/private/qabstracttexture_p.h> -#include <Qt3DRender/qtexturegenerator.h> -#include <Qt3DExtras/private/areaallocator_p.h> -#include <Qt3DExtras/qtextureatlas.h> +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qabstracttexture.h> QT_BEGIN_NAMESPACE namespace Qt3DExtras { -// Used to store texture info within atlas -struct AtlasTexture -{ - QRect position; - int padding = 0; -}; +class QTextureAtlasPrivate; -// data shared between QTextureAtlasPrivate and the QTextureGenerators -// we use this extra indirection so we can lazily copy the sub-images -// into the actual texture image in the backend texture loader thread. -class QTextureAtlasData +class QTextureAtlas : public Qt3DRender::QAbstractTexture { -public: - QTextureAtlasData(int w, int h, QImage::Format fmt); - ~QTextureAtlasData(); - - int width() const { return m_image.width(); } - int height() const { return m_image.height(); } + Q_OBJECT - void addImage(const AtlasTexture &texture, const QImage &image); - QByteArray createUpdatedImageData(); - -private: - struct Update { - AtlasTexture textureInfo; - QImage image; - }; - - QMutex m_mutex; - QImage m_image; - QVector<Update> m_updates; -}; - -typedef QSharedPointer<QTextureAtlasData> QTextureAtlasDataPtr; - -class QTextureAtlasPrivate : public Qt3DRender::QAbstractTexturePrivate -{ public: - QTextureAtlasPrivate(); - ~QTextureAtlasPrivate(); + typedef int TextureId; + static Q_CONSTEXPR TextureId InvalidTexture = -1; - Q_DECLARE_PUBLIC(QTextureAtlas) + QTextureAtlas(Qt3DCore::QNode *parent = nullptr); + ~QTextureAtlas(); - QTextureAtlas::TextureId m_currId = 1; // IDs for new sub-textures - int m_currGen = 0; + QOpenGLTexture::PixelFormat pixelFormat() const; + void setPixelFormat(QOpenGLTexture::PixelFormat fmt); - QTextureAtlasDataPtr m_data; - QScopedPointer<AreaAllocator> m_allocator; - QOpenGLTexture::PixelFormat m_pixelFormat; - QHash<QTextureAtlas::TextureId, AtlasTexture> m_textures; -}; + TextureId addImage(const QImage &image, int padding); + void removeImage(TextureId id); -class QTextureAtlasGenerator : public Qt3DRender::QTextureGenerator -{ -public: - QTextureAtlasGenerator(const QTextureAtlasPrivate *texAtlas); - ~QTextureAtlasGenerator(); - Qt3DRender::QTextureDataPtr operator()() Q_DECL_OVERRIDE; - bool operator==(const QTextureGenerator &other) const Q_DECL_OVERRIDE; + int imageCount() const; - QT3D_FUNCTOR(QTextureAtlasGenerator) + bool hasImage(TextureId id) const; + QRect imagePosition(TextureId id) const; + QRectF imageTexCoords(TextureId id) const; + int imagePadding(TextureId id) const; private: - QTextureAtlasDataPtr m_data; - Qt3DRender::QAbstractTexture::TextureFormat m_format; - QOpenGLTexture::PixelFormat m_pixelFormat; - int m_generation; - Qt3DCore::QNodeId m_atlasId; + Q_DECLARE_PRIVATE(QTextureAtlas) }; -typedef QSharedPointer<QTextureAtlasGenerator> QTextureAtlasGeneratorPtr; } // namespace Qt3DExtras diff --git a/src/extras/text/qtextureatlas_p_p.h b/src/extras/text/qtextureatlas_p_p.h new file mode 100644 index 000000000..ca18a263a --- /dev/null +++ b/src/extras/text/qtextureatlas_p_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTEXTUREATLAS_P_P_H +#define QT3DEXTRAS_QTEXTUREATLAS_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qscopedpointer.h> +#include <Qt3DRender/private/qabstracttexture_p.h> +#include <Qt3DRender/qtexturegenerator.h> +#include <Qt3DExtras/private/areaallocator_p.h> +#include <Qt3DExtras/private/qtextureatlas_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +// Used to store texture info within atlas +struct AtlasTexture +{ + QRect position; + int padding = 0; +}; + +// data shared between QTextureAtlasPrivate and the QTextureGenerators +// we use this extra indirection so we can lazily copy the sub-images +// into the actual texture image in the backend texture loader thread. +class QTextureAtlasData +{ +public: + QTextureAtlasData(int w, int h, QImage::Format fmt); + ~QTextureAtlasData(); + + int width() const { return m_image.width(); } + int height() const { return m_image.height(); } + + void addImage(const AtlasTexture &texture, const QImage &image); + QByteArray createUpdatedImageData(); + +private: + struct Update { + AtlasTexture textureInfo; + QImage image; + }; + + QMutex m_mutex; + QImage m_image; + QVector<Update> m_updates; +}; + +typedef QSharedPointer<QTextureAtlasData> QTextureAtlasDataPtr; + +class QTextureAtlasPrivate : public Qt3DRender::QAbstractTexturePrivate +{ +public: + QTextureAtlasPrivate(); + ~QTextureAtlasPrivate(); + + Q_DECLARE_PUBLIC(QTextureAtlas) + + QTextureAtlas::TextureId m_currId = 1; // IDs for new sub-textures + int m_currGen = 0; + + QTextureAtlasDataPtr m_data; + QScopedPointer<AreaAllocator> m_allocator; + QOpenGLTexture::PixelFormat m_pixelFormat; + QHash<QTextureAtlas::TextureId, AtlasTexture> m_textures; +}; + +class QTextureAtlasGenerator : public Qt3DRender::QTextureGenerator +{ +public: + QTextureAtlasGenerator(const QTextureAtlasPrivate *texAtlas); + ~QTextureAtlasGenerator(); + Qt3DRender::QTextureDataPtr operator()() Q_DECL_OVERRIDE; + bool operator==(const QTextureGenerator &other) const Q_DECL_OVERRIDE; + + QT3D_FUNCTOR(QTextureAtlasGenerator) + +private: + QTextureAtlasDataPtr m_data; + Qt3DRender::QAbstractTexture::TextureFormat m_format; + QOpenGLTexture::PixelFormat m_pixelFormat; + int m_generation; + Qt3DCore::QNodeId m_atlasId; +}; +typedef QSharedPointer<QTextureAtlasGenerator> QTextureAtlasGeneratorPtr; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTEXTUREATLAS_P_P_H diff --git a/src/extras/text/text.pri b/src/extras/text/text.pri index 24ab40cc2..583d91de6 100644 --- a/src/extras/text/text.pri +++ b/src/extras/text/text.pri @@ -1,15 +1,14 @@ HEADERS += \ - $$PWD/qtextureatlas.h \ - $$PWD/qtextureatlas_p.h \ - $$PWD/qdistancefieldglyphcache.h \ - $$PWD/qdistancefieldglyphcache_p.h \ $$PWD/qdistancefieldmaterial.h \ $$PWD/qdistancefieldmaterial_p.h \ $$PWD/distancefieldtextrenderer_p.h \ $$PWD/distancefieldtextrenderer_p_p.h \ $$PWD/qdistancefieldtext.h \ $$PWD/qdistancefieldtext_p.h \ - $$PWD/areaallocator_p.h + $$PWD/areaallocator_p.h \ + $$PWD/qdistancefieldglyphcache_p.h \ + $$PWD/qtextureatlas_p_p.h \ + $$PWD/qtextureatlas_p.h SOURCES += \ $$PWD/qtextureatlas.cpp \ diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp index 8aad63178..29a5d9883 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp @@ -68,8 +68,6 @@ #include <Qt3DExtras/qcylindergeometry.h> #include <Qt3DExtras/qextrudedtextgeometry.h> #include <Qt3DExtras/qextrudedtextmesh.h> -#include <Qt3DExtras/qtextureatlas.h> -#include <Qt3DExtras/qdistancefieldglyphcache.h> #include <Qt3DExtras/qdistancefieldtext.h> #include <Qt3DExtras/qmorphphongmaterial.h> #include <Qt3DQuickExtras/private/quick3dlevelofdetailloader_p.h> @@ -126,7 +124,6 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DExtras::QExtrudedTextGeometry>(uri, 2, 9, "ExtrudedTextGeometry"); qmlRegisterType<Qt3DExtras::QExtrudedTextMesh>(uri, 2, 9, "ExtrudedTextMesh"); - qmlRegisterType<Qt3DExtras::QDistanceFieldGlyphCache>(uri, 2, 9, "DistanceFieldGlyphCache"); qmlRegisterType<Qt3DExtras::QDistanceFieldText>(uri, 2, 9, "DistanceFieldText"); } diff --git a/tests/manual/distancefieldtext/TextScene.qml b/tests/manual/distancefieldtext/TextScene.qml index 2d60a1c67..54757b400 100644 --- a/tests/manual/distancefieldtext/TextScene.qml +++ b/tests/manual/distancefieldtext/TextScene.qml @@ -91,10 +91,6 @@ Entity { } ] - DistanceFieldGlyphCache { - id: glyphCache - } - function getChars(n) { var s = ""; for (var i = 0; i < n; i++) { @@ -148,7 +144,6 @@ Entity { font.pointSize: 10 text: getChars(strLen) - glyphCache: glyphCache position: Qt.rect(-10, -5, 20, 10) fontScale: 0.1 } |