diff options
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/Qt3DSQtTextRenderer.cpp')
m--------- | src/Runtime/ogl-runtime | 0 | ||||
-rw-r--r-- | src/Runtime/ogl-runtime/src/runtimerender/Qt3DSQtTextRenderer.cpp | 655 |
2 files changed, 0 insertions, 655 deletions
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime new file mode 160000 +Subproject 427fddb50d43aa21a90fc7356ee3cdd8a908df5 diff --git a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSQtTextRenderer.cpp b/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSQtTextRenderer.cpp deleted file mode 100644 index 029ccea2..00000000 --- a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSQtTextRenderer.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008-2012 NVIDIA Corporation. -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt 3D Studio. -** -** $QT_BEGIN_LICENSE:GPL$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 or (at your option) 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.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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "Qt3DSTextRenderer.h" -#include "Qt3DSRenderText.h" -#include "foundation/Qt3DSFoundation.h" -#include "foundation/StringTable.h" -#include "foundation/Qt3DSBroadcastingAllocator.h" - -#include "foundation/Qt3DSVec2.h" -#include "foundation/FileTools.h" -#include "render/Qt3DSRenderContext.h" -#include "foundation/Qt3DSContainers.h" -#include "Qt3DSRenderThreadPool.h" -#include "foundation/Qt3DSSync.h" -#include "foundation/Qt3DSPerfTimer.h" -#include "EASTL/set.h" -#include "EASTL/list.h" - -#include <QPainter> -#include <QImage> -#include <QFontDatabase> -#include <QDir> -#include <QDebug> -#include <QHash> -#include <QGuiApplication> -#include <QtMath> -#include <QRawFont> - -using namespace qt3ds::render; - -namespace { - -struct Qt3DSQtTextRenderer : public ITextRenderer -{ - struct FontInfo - { - QString fontFileName; - QString fontName; - QString fontFamily; - int fontId; - QFont font; - - FontInfo() : - fontId(-1) - {} - - FontInfo(const QString &fileName, const QString &name, const QString &family, int id) : - fontFileName(fileName) - , fontName(name) - , fontFamily(family) - , fontId(id) - { - font.setFamily(fontFamily); - } - - FontInfo(const FontInfo &other) : - fontFileName(other.fontFileName) - , fontName(other.fontName) - , fontFamily(other.fontFamily) - , fontId(other.fontId) - , font(other.font) - {} - - FontInfo &operator=(const FontInfo &other) - { - fontFileName = other.fontFileName; - fontName = other.fontName; - fontFamily = other.fontFamily; - fontId = other.fontId; - font = other.font; - - return *this; - } - }; - - typedef eastl::string TStrType; - typedef eastl::set<TStrType> TStringSet; - typedef QHash<QString, FontInfo> TFontInfoHash; - - NVFoundationBase &m_foundation; - NVScopedRefCounted<IStringTable> m_stringTable; - NVScopedRefCounted<NVRenderContext> m_renderContext; - NVScopedRefCounted<IPerfTimer> m_perfTimer; - volatile QT3DSI32 mRefCount; - nvvector<SRendererFontEntry> m_installedFonts; - - Sync m_PreloadSync; - - TStringSet m_systemFontDirs; - TStringSet m_projectFontDirs; - TFontInfoHash m_projectFontInfos; - TFontInfoHash m_systemFontInfos; - TStrType m_workspace; - - bool m_systemFontsInitialized; - bool m_projectFontsInitialized; - bool m_PreloadingFonts; - - QStringList m_nameFilters; - qreal m_pixelRatio; - - Qt3DSQtTextRenderer(NVFoundationBase &inFoundation, IStringTable &inStrTable) - : m_foundation(inFoundation) - , m_stringTable(inStrTable) - , mRefCount(0) - , m_installedFonts(inFoundation.getAllocator(), "Qt3DSQtTextRenderer::m_installedFonts") - , m_PreloadSync(inFoundation.getAllocator()) - , m_systemFontsInitialized(false) - , m_projectFontsInitialized(false) - , m_PreloadingFonts(false) - , m_pixelRatio(1.0) - { - const QWindowList list = QGuiApplication::topLevelWindows(); - if (list.size() > 0) - m_pixelRatio = list[0]->devicePixelRatio(); - - m_nameFilters << QStringLiteral("*.ttf"); - m_nameFilters << QStringLiteral("*.otf"); - } - virtual ~Qt3DSQtTextRenderer() - { - QFontDatabase::removeAllApplicationFonts(); - } - - QString stringToQString(const CRegisteredString &str) - { - return QString::fromUtf8(str.c_str()); - } - - QString stringToQString(const eastl::string &str) - { - return QString::fromUtf8(str.c_str()); - } - - QString stringToQString(const char8_t *str) - { - return QString::fromUtf8(str); - } - - CRegisteredString QStringToRegisteredString(const QString &str) - { - return m_stringTable->RegisterStr(str.toUtf8().constData()); - } - - void unregisterProjectFonts() - { - for (FontInfo &fi : m_projectFontInfos.values()) - QFontDatabase::removeApplicationFont(fi.fontId); - m_projectFontsInitialized = false; - m_installedFonts.clear(); - m_projectFontInfos.clear(); - } - - QString getFileStem(const QString &fileName) - { - QString retVal; - int dotPos = fileName.lastIndexOf(QChar('.')); - if (dotPos < 0) - return retVal; - int slashPos = fileName.lastIndexOf(QChar('/')); - retVal = fileName.mid(slashPos + 1); - retVal.chop(fileName.length() - dotPos); - return retVal; - } - - void registerFonts(TStringSet dirSet, TFontInfoHash *fontInfos = nullptr) - { - for (TStringSet::const_iterator theIter = dirSet.begin(), - theEnd = dirSet.end(); - theIter != theEnd; ++theIter) { - QString localDir = CFileTools::NormalizePathForQtUsage(stringToQString(*theIter)); - QDir dir(localDir); - if (!dir.exists()) { - qWarning("Attempted to register invalid font directory: %s", - qPrintable(localDir)); - continue; - } - QStringList entryList = dir.entryList(m_nameFilters); - for (QString entry : entryList) { - entry = dir.absoluteFilePath(entry); - QFile file(entry); - if (file.open(QIODevice::ReadOnly)) { - QByteArray rawData = file.readAll(); - int fontId = QFontDatabase::addApplicationFontFromData(rawData); - if (fontId < 0) { - qCWarning(WARNING, "Failed to register font: %s", - entry.toStdString().c_str()); - } else if (fontInfos) { - QString fontName = getFileStem(entry); - QString fontFamily; - QStringList families = QFontDatabase::applicationFontFamilies(fontId); - if (families.size() > 0) - fontFamily = families.at(0); - FontInfo fi(entry, fontName, fontFamily, fontId); - // Detect font style and weight using a dummy QRawFont - QRawFont rawFont(rawData, 16); - if (rawFont.isValid()) { - if (rawFont.style() != QFont::StyleOblique) { - fi.font.setStyle(rawFont.style()); - fi.font.setWeight(rawFont.weight()); - } - } else { - qCWarning(WARNING, "Failed to determine font style: %s", - entry.toStdString().c_str()); - } - fontInfos->insert(fontName, fi); - } - } else { - qCWarning(WARNING, "Failed to load font: %s", - entry.toStdString().c_str()); - } - } - } - } - - void projectCleanup() - { - m_projectFontsInitialized = false; - unregisterProjectFonts(); - m_projectFontDirs.clear(); - } - - QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_foundation.getAllocator()) - - eastl::pair<TStrType, bool> AddFontDirectory(const TStrType &inDirectory, TStringSet &inDirSet) - { - if (inDirectory.empty()) { - m_workspace.assign("./"); - } else { - m_workspace.clear(); - for (const char8_t *item = inDirectory.c_str(); item && *item; ++item) { - if (*item == '\\') - m_workspace.append(1, '/'); - else - m_workspace.append(1, static_cast<char8_t>(*item)); - } - if (m_workspace.back() != '/') - m_workspace.append(1, '/'); - } - - return eastl::make_pair(m_workspace, inDirSet.insert(m_workspace).second); - } - - // You can have several standard font directories and these will be persistent - void AddSystemFontDirectory(const char8_t *inDirectory) override - { - AddFontDirectory(inDirectory, m_systemFontDirs); - } - - void AddProjectFontDirectory(const char8_t *inProjectDirectory) override - { - eastl::pair<TStrType, bool> theAddResult = - AddFontDirectory(inProjectDirectory, m_projectFontDirs); - if (theAddResult.second && m_projectFontsInitialized) - ReloadFonts(); - } - - void ReloadFonts() override - { - unregisterProjectFonts(); - PreloadFonts(); - } - - void PreloadFonts() override - { - if (!m_systemFontsInitialized) { - m_systemFontsInitialized = true; - registerFonts(m_systemFontDirs, &m_systemFontInfos); - } - - if (!m_projectFontsInitialized) { - m_projectFontsInitialized = true; - registerFonts(m_projectFontDirs, &m_projectFontInfos); - } - } - - void ClearProjectFontDirectories() override - { - projectCleanup(); - } - - static void PreloadThreadCallback(void *inData) - { - Qt3DSQtTextRenderer *theRenderer(reinterpret_cast<Qt3DSQtTextRenderer *>(inData)); - theRenderer->PreloadFonts(); - theRenderer->m_PreloadSync.set(); - } - - void BeginPreloadFonts(IThreadPool &inThreadPool, IPerfTimer &inTimer) override - { - m_PreloadingFonts = true; - - m_PreloadSync.reset(); - m_perfTimer = inTimer; - - inThreadPool.AddTask(this, PreloadThreadCallback, NULL); - } - - void EndPreloadFonts() override - { - if (m_PreloadingFonts) { - { - SStackPerfTimer __perfTimer(*m_perfTimer, "QtText: Wait till font preloading completed"); - m_PreloadSync.wait(); - } - } - m_PreloadingFonts = false; - } - - // Get the list of project fonts. These are the only fonts that can be displayed. - NVConstDataRef<SRendererFontEntry> GetProjectFontList() override - { - PreloadFonts(); - if (m_installedFonts.empty()) { - m_installedFonts.reserve(m_projectFontInfos.size()); - for (FontInfo &fi : m_projectFontInfos.values()) { - m_installedFonts.push_back(SRendererFontEntry( - fi.fontName, - fi.fontFileName)); - } - - } - return m_installedFonts; - } - - Option<CRegisteredString> GetFontNameForFont(CRegisteredString inFontname) override - { - // This function is there to support legacy font names. - - QString inStr = stringToQString(inFontname); - if (m_projectFontInfos.keys().contains(inStr)) - return inFontname; - - // Fall back for family name detection if not found by font name - for (FontInfo &fi : m_projectFontInfos.values()) { - if (inStr == fi.fontFamily) - return QStringToRegisteredString(fi.fontName); - } - - return Empty(); - } - - Option<CRegisteredString> GetFontNameForFont(const char8_t *inFontname) override - { - return GetFontNameForFont(m_stringTable->RegisterStr(inFontname)); - } - - ITextRenderer &GetTextRenderer(NVRenderContext &inRenderContext) override - { - m_renderContext = inRenderContext; - return *this; - } - - FontInfo &fontInfoForName(const CRegisteredString &fontName) - { - PreloadFonts(); - QString qtFontName = stringToQString(fontName); - if (m_projectFontInfos.contains(qtFontName)) - return m_projectFontInfos[qtFontName]; - - if (m_systemFontInfos.contains(qtFontName)) - return m_systemFontInfos[qtFontName]; - - // Unknown font, create a system font for it - FontInfo fi("", qtFontName, qtFontName, -1); - m_systemFontInfos.insert(qtFontName, fi); - - return m_systemFontInfos[qtFontName]; - } - - void updateFontInfo(FontInfo &fi, const STextRenderInfo &inText, - QT3DSF32 inTextScaleFactor = 1.0f) - { - qreal pixelSize = inText.m_FontSize; - fi.font.setPixelSize(pixelSize * inTextScaleFactor); - fi.font.setLetterSpacing(QFont::AbsoluteSpacing, qreal(inText.m_Tracking)); - } - - QStringList splitText(const char8_t *theText) - { - // Split the text into lines - int lines = 1; - int lineLen = 0; - QStringList lineList; - const char8_t *lineStartItem = nullptr; - for (const char8_t *item = theText; item && *item; ++item) { - if (!lineLen) - lineStartItem = item; - ++lineLen; - if (*item == '\n') { - int chopAmount = 1; - if (lineLen > 1 && *(item - 1) == '\r') - ++chopAmount; - - ++lines; - lineList.append(QString::fromUtf8(lineStartItem, lineLen - chopAmount)); - lineLen = 0; - } - } - if (lineStartItem) - lineList.append(QString::fromUtf8(lineStartItem, lineLen)); - - return lineList; - } - - QRectF textBoundingBox(const STextRenderInfo &inText, - const QFontMetricsF &fm, QStringList &lineList, - QVector<qreal> &lineWidths, const char8_t *inTextOverride = nullptr) - { - const char8_t *theText = inTextOverride ? inTextOverride : inText.m_Text.c_str(); - lineList = splitText(theText); - - QRectF boundingBox; - boundingBox.setHeight(lineList.size() * fm.height() + qCeil(qreal(lineList.size() - 1) * qreal(inText.m_Leading))); - - lineWidths.resize(lineList.size()); - - for (int i = 0; i < lineList.size(); ++i) { - // For italicized fonts the bounding box right is the correct method - // to measure since the left offset may extend, but for - // non-italicized fonts we need the width method to meausure - // otherwise the resultant text will be clipped. - QString line = lineList.at(i); - qreal width = fm.width(line); - qreal right = fm.boundingRect(line).right(); - // For hdpi displays, fontmetrics doesn't always calculate enough space for fonts, so - // we add the pixel ratio to all widths to avoid clipping - qreal lineWidth = qMax(width, right) + m_pixelRatio; - lineWidths[i] = lineWidth; - if (boundingBox.width() < lineWidth) - boundingBox.setWidth(lineWidth); - } - - // We don't want extra letter spacing on the last glyph, so let's remove it - boundingBox.setRight(qMax(boundingBox.left(), boundingBox.right() - qFloor(inText.m_Tracking))); - - return boundingBox; - } - - STextDimensions MeasureText(const STextRenderInfo &inText, QT3DSF32 inTextScaleFactor, - const char8_t *inTextOverride) override - { - FontInfo &fi = fontInfoForName(inText.m_Font); - updateFontInfo(fi, inText, inTextScaleFactor); - QFontMetricsF fm(fi.font); - QStringList dummyList; - QVector<qreal> dummyWidth; - QRectF boundingBox = textBoundingBox(inText, fm, dummyList, dummyWidth, inTextOverride); - return STextDimensions(boundingBox.width(), boundingBox.height()); - } - - int alignToQtAlign(TextVerticalAlignment::Enum va) - { - int qtAlign(0); - switch (va) { - case TextVerticalAlignment::Top: - qtAlign = Qt::AlignTop; - break; - case TextVerticalAlignment::Bottom: - qtAlign = Qt::AlignBottom; - break; - default: - qtAlign = Qt::AlignVCenter; - } - - return qtAlign; - } - - STextTextureDetails RenderText(const STextRenderInfo &inSrcText, - NVRenderTexture2D &inTexture) override - { - FontInfo &fi = fontInfoForName(inSrcText.m_Font); - updateFontInfo(fi, inSrcText); - QFontMetricsF fm(fi.font); - int horizontalAlignmentFlag = Qt::AlignLeft; - - int shadowRgb = int(2.55f * (100 - int(inSrcText.m_DropShadowStrength))); - QStringList lineList; - QVector<qreal> lineWidths; - QRectF boundingBox; - const bool dynamicTextArea = inSrcText.m_BoundingBox.isZero(); - - if (dynamicTextArea) { - boundingBox = textBoundingBox(inSrcText, fm, lineList, lineWidths); - } else { - lineList << inSrcText.m_Text.c_str(); - lineWidths << inSrcText.m_BoundingBox.x; - boundingBox = QRectF(0, 0, inSrcText.m_BoundingBox.x, inSrcText.m_BoundingBox.y); - } - - if (boundingBox.width() <= 0 || boundingBox.height() <= 0) { - return ITextRenderer::UploadData(toU8DataRef((char *)nullptr, 0), inTexture, 4, 4, - 0, 0, - NVRenderTextureFormats::RGBA8, true); - } - - int finalWidth = NextMultipleOf4(boundingBox.width()); - int finalHeight = NextMultipleOf4(boundingBox.height()); - - QImage image(finalWidth, finalHeight, QImage::Format_ARGB32); - image.fill(0); - QPainter painter(&image); - painter.setPen(Qt::white); - painter.setFont(fi.font); - - // Translate painter to remove the extra spacing of the last letter - qreal tracking = 0.0; - switch (inSrcText.m_HorizontalAlignment) { - case TextHorizontalAlignment::Center: - horizontalAlignmentFlag = Qt::AlignHCenter; - tracking += qreal(inSrcText.m_Tracking / 2.0f); - break; - case TextHorizontalAlignment::Right: - horizontalAlignmentFlag = Qt::AlignRight; - tracking += qreal(inSrcText.m_Tracking); - break; - default: - break; // Do nothing - } - - int wordWrapFlags = 0; - if (dynamicTextArea) { - wordWrapFlags = Qt::TextDontClip; - } else { - switch (inSrcText.m_WordWrap) { - case TextWordWrap::WrapWord: - wordWrapFlags = Qt::TextWordWrap | Qt::TextDontClip; - break; - case TextWordWrap::WrapAnywhere: - wordWrapFlags = Qt::TextWrapAnywhere | Qt::TextDontClip; - break; - case TextWordWrap::Clip: - default: - break; - } - } - - int lineHeight = dynamicTextArea ? fm.height() : finalHeight; - QT3DSF32 nextHeight = 0; - for (int i = 0; i < lineList.size(); ++i) { - const QString &line = lineList.at(i); - qreal xTranslation = tracking; - switch (inSrcText.m_HorizontalAlignment) { - case TextHorizontalAlignment::Center: - xTranslation += qreal(boundingBox.width() - lineWidths.at(i)) / 2.0; - break; - case TextHorizontalAlignment::Right: - xTranslation += qreal(boundingBox.width() - lineWidths.at(i)); - break; - default: - break; // Do nothing - } - QRectF bound(xTranslation, qreal(nextHeight), lineWidths.at(i), lineHeight); - QRectF actualBound; - if (inSrcText.m_DropShadow) { - qreal shadowOffsetX = qreal(inSrcText.m_FontSize * inSrcText.m_DropShadowOffsetX) - / 1000.; - qreal shadowOffsetY = qreal(inSrcText.m_FontSize * inSrcText.m_DropShadowOffsetY) - / 1000.; - QRectF boundShadow(xTranslation + shadowOffsetX, nextHeight + shadowOffsetY, - qreal(lineWidths.at(i)), lineHeight); - // shadow is a darker shade of the given font color - painter.setPen(QColor(shadowRgb, shadowRgb, shadowRgb)); - painter.drawText(boundShadow, - alignToQtAlign(inSrcText.m_VerticalAlignment) | wordWrapFlags - | horizontalAlignmentFlag, line, &actualBound); - painter.setPen(Qt::white); // coloring is done in the shader - } - painter.drawText(bound, - alignToQtAlign(inSrcText.m_VerticalAlignment) | wordWrapFlags - | horizontalAlignmentFlag, line, &actualBound); - - nextHeight += QT3DSF32(lineHeight) + inSrcText.m_Leading; - } - - return ITextRenderer::UploadData(toU8DataRef(image.bits(), image.byteCount()), inTexture, - image.width(), image.height(), - image.width(), image.height(), - NVRenderTextureFormats::RGBA8, true); - } - - STextTextureDetails RenderText(const STextRenderInfo &inText, - NVRenderPathFontItem &inPathFontItem, - NVRenderPathFontSpecification &inFontPathSpec) override - { - Q_UNUSED(inText); - Q_UNUSED(inPathFontItem); - Q_UNUSED(inFontPathSpec); - QT3DS_ASSERT(m_renderContext->IsPathRenderingSupported()); - - // We do not support HW accelerated fonts (yet?) - QT3DS_ASSERT(false); - - return STextTextureDetails(); - } - - void BeginFrame() override - { - // Nothing to do - } - - void EndFrame() override - { - // Nothing to do - } - - // unused for text rendering via texture atlas - STextTextureAtlasEntryDetails RenderAtlasEntry(QT3DSU32, NVRenderTexture2D &) override - { - return STextTextureAtlasEntryDetails(); - } - QT3DSI32 CreateTextureAtlas() override - { - return 0; - } - SRenderTextureAtlasDetails RenderText(const STextRenderInfo &) override - { - return SRenderTextureAtlasDetails(); - } -}; -} - -ITextRendererCore &ITextRendererCore::CreateQtTextRenderer(NVFoundationBase &inFnd, - IStringTable &inStrTable) -{ - return *QT3DS_NEW(inFnd.getAllocator(), Qt3DSQtTextRenderer)(inFnd, inStrTable); -} |