diff options
author | Liang Qi <liang.qi@qt.io> | 2019-05-07 11:44:37 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-05-07 11:58:30 +0200 |
commit | c2b553784dfbe0ece90f79709639e27e74359a7d (patch) | |
tree | 04b0c74c7417a5f1b628d0b18a07f9dd8be1df60 /src/gui | |
parent | 0b373c2e36a68aedf3731fcb3cd84fd010c2d67c (diff) | |
parent | 8ea0a82a6a771dd76df2d51c6ef3ed966a5b9b45 (diff) |
Merge remote-tracking branch 'origin/5.13' into dev
Conflicts:
src/corelib/kernel/qobject.cpp
src/corelib/kernel/qvariant.h
src/corelib/tools/qlist.h
Done-With: Milian Wolff <milian.wolff@kdab.com>
Done-With: Allan Sandfeld Jensen <allan.jensen@qt.io>
Change-Id: I6803f7239aa137a51a7467fab7cc7a01302a848d
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/configure.json | 4 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 20 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 1 | ||||
-rw-r--r-- | src/gui/painting/qtriangulator_p.h | 2 | ||||
-rw-r--r-- | src/gui/qtgui.tracepoints | 2 | ||||
-rw-r--r-- | src/gui/text/qfontsubset.cpp | 4 | ||||
-rw-r--r-- | src/gui/text/qtexthtmlparser.cpp | 4 | ||||
-rw-r--r-- | src/gui/text/qtextobject.h | 1 | ||||
-rw-r--r-- | src/gui/util/qshadergenerator.cpp | 234 | ||||
-rw-r--r-- | src/gui/util/qshadergenerator_p.h | 4 |
10 files changed, 234 insertions, 42 deletions
diff --git a/src/gui/configure.json b/src/gui/configure.json index 9e76fc455e..912ad741e0 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1203,14 +1203,14 @@ "label": " Using system FreeType", "enable": "input.freetype == 'system'", "disable": "input.freetype == 'qt'", - "autoDetect": "!config.win32", + "autoDetect": "!config.msvc", "condition": "features.freetype && libs.freetype", "output": [ "privateFeature" ] }, "fontconfig": { "label": "Fontconfig", "autoDetect": "!config.darwin", - "condition": "!config.win32 && features.system-freetype && libs.fontconfig", + "condition": "!config.msvc && features.system-freetype && libs.fontconfig", "output": [ "privateFeature", "feature" ] }, "gbm": { diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 429446829e..d2858c5270 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -181,7 +181,9 @@ ulong QGuiApplicationPrivate::mousePressTime = 0; Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton; int QGuiApplicationPrivate::mousePressX = 0; int QGuiApplicationPrivate::mousePressY = 0; -int QGuiApplicationPrivate::mouse_double_click_distance = -1; + +static int mouseDoubleClickDistance = -1; +static int touchDoubleTapDistance = -1; QWindow *QGuiApplicationPrivate::currentMousePressWindow = 0; @@ -259,6 +261,12 @@ static inline void clearFontUnlocked() QGuiApplicationPrivate::app_font = 0; } +static void initThemeHints() +{ + mouseDoubleClickDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MouseDoubleClickDistance).toInt(); + touchDoubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt(); +} + static bool checkNeedPortalSupport() { #if QT_CONFIG(dbus) @@ -1523,8 +1531,7 @@ void QGuiApplicationPrivate::init() initPalette(); QFont::initialize(); - - mouse_double_click_distance = platformTheme()->themeHint(QPlatformTheme::MouseDoubleClickDistance).toInt(); + initThemeHints(); #ifndef QT_NO_CURSOR QCursorData::initialize(); @@ -2036,8 +2043,10 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (mouseMove) { QGuiApplicationPrivate::lastCursorPosition = globalPoint; - if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance|| - qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance) + const auto doubleClickDistance = e->source == Qt::MouseEventNotSynthesized ? + mouseDoubleClickDistance : touchDoubleTapDistance; + if (qAbs(globalPoint.x() - mousePressX) > doubleClickDistance || + qAbs(globalPoint.y() - mousePressY) > doubleClickDistance) mousePressButton = Qt::NoButton; } else { mouse_buttons = e->buttons; @@ -3963,6 +3972,7 @@ void QGuiApplicationPrivate::notifyThemeChanged() clearFontUnlocked(); initFontUnlocked(); } + initThemeHints(); } void QGuiApplicationPrivate::sendApplicationPaletteChange(bool toAllWidgets, const char *className) diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index c9619daa3d..361519661a 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -216,7 +216,6 @@ public: static Qt::MouseButton mousePressButton; static int mousePressX; static int mousePressY; - static int mouse_double_click_distance; static QPointF lastCursorPosition; static QWindow *currentMouseWindow; static QWindow *currentMousePressWindow; diff --git a/src/gui/painting/qtriangulator_p.h b/src/gui/painting/qtriangulator_p.h index 8f043fc925..c9ae2571f4 100644 --- a/src/gui/painting/qtriangulator_p.h +++ b/src/gui/painting/qtriangulator_p.h @@ -93,6 +93,8 @@ public: return indices16.size(); } + QVertexIndexVector() = default; + QVertexIndexVector(const QVertexIndexVector &other) = default; inline QVertexIndexVector &operator = (const QVertexIndexVector &other) { if (t == UnsignedInt) diff --git a/src/gui/qtgui.tracepoints b/src/gui/qtgui.tracepoints index 0a96a589b1..52916a3aa2 100644 --- a/src/gui/qtgui.tracepoints +++ b/src/gui/qtgui.tracepoints @@ -8,7 +8,7 @@ QGuiApplicationPrivate_init_entry() QGuiApplicationPrivate_init_exit() QGuiApplicationPrivate_processWindowSystemEvent_entry(int type) -QGuiApplicationPrivate_processWindowSystemEvent_exit(int type) +QGuiApplicationPrivate_processWindowSystemEvent_exit() QFontDatabase_addApplicationFont(const QString &filename) QFontDatabase_load(const QString &family, int pointSize) diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index f5fc562e13..fb12b681a4 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -49,6 +49,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_PDF + // This map is used for symbol fonts to get the correct glyph names for the latin range static const unsigned short symbol_map[0x100] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, @@ -90,7 +92,7 @@ static const unsigned short symbol_map[0x100] = { // ---------------------------- PS/PDF helper methods ----------------------------------- -#ifndef QT_NO_PDF + QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol) { diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index adc3b138f7..895232e4c7 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1721,6 +1721,8 @@ QStringList QTextHtmlStyleSelector::nodeNames(NodePtr node) const #endif // QT_NO_CSSPARSER +#ifndef QT_NO_CSSPARSER + static inline int findAttribute(const QStringList &attributes, const QString &name) { int idx = -1; @@ -1730,8 +1732,6 @@ static inline int findAttribute(const QStringList &attributes, const QString &na return idx; } -#ifndef QT_NO_CSSPARSER - QString QTextHtmlStyleSelector::attribute(NodePtr node, const QString &name) const { const QStringList &attributes = parser->at(node.id).attributes; diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 586a593dd2..215a76fb4d 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -263,6 +263,7 @@ public: iterator() : p(nullptr), b(0), e(0), n(0) {} #if QT_VERSION < QT_VERSION_CHECK(6,0,0) iterator(const iterator &o) : p(o.p), b(o.b), e(o.e), n(o.n) {} + iterator &operator=(const iterator &o) = default; #endif QTextFragment fragment() const; diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp index 205118f41c..bcb985de54 100644 --- a/src/gui/util/qshadergenerator.cpp +++ b/src/gui/util/qshadergenerator.cpp @@ -44,6 +44,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg) + namespace { QByteArray toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format) @@ -342,18 +344,120 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) code << QByteArrayLiteral("void main()"); code << QByteArrayLiteral("{"); - // Table to store temporary variables that should be replaced by global - // variables. This avoids having vec3 v56 = vertexPosition; when we could + const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+)).*;$")); + const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("^(.*\\s+(v\\d+))\\s*=\\s*(.*);$")); + const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); + const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("^\\s*(\\w+)\\s*=\\s*(.*);$")); + + struct Variable; + + struct Assignment + { + QString expression; + QVector<Variable *> referencedVariables; + }; + + struct Variable + { + enum Type { + GlobalInput, + TemporaryAssignment, + Output + }; + + QString name; + QString declaration; + int referenceCount = 0; + Assignment assignment; + Type type = TemporaryAssignment; + bool substituted = false; + + static void substitute(Variable *v) + { + if (v->substituted) + return; + + qCDebug(ShaderGenerator) << "Begin Substituting " << v->name << " = " << v->assignment.expression; + for (Variable *ref : qAsConst(v->assignment.referencedVariables)) { + // Recursively substitute + Variable::substitute(ref); + + // Replace all variables referenced only once in the assignment + // by their actual expression + if (ref->referenceCount == 1 || ref->type == Variable::GlobalInput) { + const QRegularExpression r(QStringLiteral("(.*\\b)(%1)(\\b.*)").arg(ref->name)); + if (v->assignment.referencedVariables.size() == 1) + v->assignment.expression.replace(r, + QStringLiteral("\\1%2\\3").arg(ref->assignment.expression)); + else + v->assignment.expression.replace(r, + QStringLiteral("(\\1%2\\3)").arg(ref->assignment.expression)); + } + } + qCDebug(ShaderGenerator) << "Done Substituting " << v->name << " = " << v->assignment.expression; + v->substituted = true; + } + }; + + struct LineContent + { + QByteArray rawContent; + Variable *var = nullptr; + }; + + // Table to store temporary variables that should be replaced: + // - If variable references a a global variables + // -> we will use the global variable directly + // - If variable references a function results + // -> will be kept only if variable is referenced more than once. + // This avoids having vec3 v56 = vertexPosition; when we could // just use vertexPosition directly. // The added benefit is when having arrays, we don't try to create // mat4 v38 = skinningPalelette[100] which would be invalid - QHash<QString, QString> localReferencesToGlobalInputs; - const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*(\\w+).*;$")); + QVector<Variable> temporaryVariables; + // Reserve more than enough space to ensure no reallocation will take place + temporaryVariables.reserve(nodes.size() * 8); + + QVector<LineContent> lines; + + auto createVariable = [&] () -> Variable * { + Q_ASSERT(temporaryVariables.capacity() > 0); + temporaryVariables.resize(temporaryVariables.size() + 1); + return &temporaryVariables.last(); + }; + + auto findVariable = [&] (const QString &name) -> Variable * { + const auto end = temporaryVariables.end(); + auto it = std::find_if(temporaryVariables.begin(), end, + [=] (const Variable &a) { return a.name == name; }); + if (it != end) + return &(*it); + return nullptr; + }; + + auto gatherTemporaryVariablesFromAssignment = [&] (Variable *v, const QString &assignmentContent) { + QRegularExpressionMatchIterator subMatchIt = temporaryVariableInAssignmentRegExp.globalMatch(assignmentContent); + while (subMatchIt.hasNext()) { + const QRegularExpressionMatch subMatch = subMatchIt.next(); + const QString variableName = subMatch.captured(1); + + // Variable we care about should already exists -> an expression cannot reference a variable that hasn't been defined + Variable *u = findVariable(variableName); + Q_ASSERT(u); + + // Increase reference count for u + ++u->referenceCount; + // Insert u as reference for variable v + v->assignment.referencedVariables.push_back(u); + } + }; for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) { const QShaderNode node = statement.node; QByteArray line = node.rule(format).substitution; const QVector<QShaderNodePort> ports = node.ports(); + + // Generate temporary variable names vN for (const QShaderNodePort &port : ports) { const QString portName = port.name; const QShaderNodePort::Direction portDirection = port.direction; @@ -374,47 +478,117 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) line.replace(placeholder, variable); } + // Substitute variable names by generated vN variable names const QByteArray substitutionedLine = replaceParameters(line, node, format); + Variable *v = nullptr; + + switch (node.type()) { // Record name of temporary variable that possibly references a global input // We will replace the temporary variables by the matching global variables later - bool isAGlobalInputVariable = false; - if (node.type() == QShaderNode::Input) { + case QShaderNode::Input: { const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine)); if (match.hasMatch()) { + const QString localVariable = match.captured(1); const QString globalVariable = match.captured(2); - if (globalInputVariables.contains(globalVariable)) { - const QString localVariable = match.captured(1); - // TO DO: Clean globalVariable (remove brackets ...) - localReferencesToGlobalInputs.insert(localVariable, globalVariable); - isAGlobalInputVariable = true; - } + + v = createVariable(); + v->name = localVariable; + v->type = Variable::GlobalInput; + + Assignment assignment; + assignment.expression = globalVariable; + v->assignment = assignment; + } + break; + } + + case QShaderNode::Function: { + const QRegularExpressionMatch match = temporaryVariableToAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); + if (match.hasMatch()) { + const QString localVariableDeclaration = match.captured(1); + const QString localVariableName = match.captured(2); + const QString assignmentContent = match.captured(3); + + // Add new variable -> it cannot exist already + v = createVariable(); + v->name = localVariableName; + v->declaration = localVariableDeclaration; + v->assignment.expression = assignmentContent; + + // Find variables that may be referenced in the assignment + gatherTemporaryVariablesFromAssignment(v, assignmentContent); + } + break; + } + + case QShaderNode::Output: { + const QRegularExpressionMatch match = outputToTemporaryAssignmentRegExp.match(QString::fromUtf8(substitutionedLine)); + if (match.hasMatch()) { + const QString outputDeclaration = match.captured(1); + const QString assignmentContent = match.captured(2); + + v = createVariable(); + v->name = outputDeclaration; + v->declaration = outputDeclaration; + v->type = Variable::Output; + + Assignment assignment; + assignment.expression = assignmentContent; + v->assignment = assignment; + + // Find variables that may be referenced in the assignment + gatherTemporaryVariablesFromAssignment(v, assignmentContent); } + break; + } + case QShaderNode::Invalid: + break; } - // Only insert content for lines aren't inputs or have not matching - // globalVariables for now - if (!isAGlobalInputVariable) - code << QByteArrayLiteral(" ") + substitutionedLine; + LineContent lineContent; + lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); + lineContent.var = v; + lines << lineContent; } - code << QByteArrayLiteral("}"); - code << QByteArray(); + // Go through all lines + // Perform substitution of line with temporary variables substitution + for (LineContent &lineContent : lines) { + Variable *v = lineContent.var; + qCDebug(ShaderGenerator) << lineContent.rawContent; + if (v != nullptr) { + Variable::substitute(v); + + qCDebug(ShaderGenerator) << "Line " << lineContent.rawContent << "is assigned to temporary" << v->name; + + // Check number of occurrences a temporary variable is referenced + if (v->referenceCount == 1 || v->type == Variable::GlobalInput) { + // If it is referenced only once, no point in creating a temporary + // Clear content for current line + lineContent.rawContent.clear(); + // We assume expression that were referencing vN will have vN properly substituted + } else { + lineContent.rawContent = QStringLiteral(" %1 = %2;").arg(v->declaration) + .arg(v->assignment.expression) + .toUtf8(); + } - // Replace occurrences of local variables which reference a global variable - // by the global variables directly - auto it = localReferencesToGlobalInputs.cbegin(); - const auto end = localReferencesToGlobalInputs.cend(); - QString codeString = QString::fromUtf8(code.join('\n')); - - while (it != end) { - const QRegularExpression r(QStringLiteral("\\b(%1)([\\b|\\.|;|\\)|\\[|\\s|\\*|\\+|\\/|\\-|,])").arg(it.key()), - QRegularExpression::MultilineOption); - codeString.replace(r, QStringLiteral("%1\\2").arg(it.value())); - ++it; + qCDebug(ShaderGenerator) << "Updated Line is " << lineContent.rawContent; + } } - return codeString.toUtf8(); + // Go throug all lines and insert content + for (const LineContent &lineContent : qAsConst(lines)) { + if (!lineContent.rawContent.isEmpty()) { + code << lineContent.rawContent; + } + } + + code << QByteArrayLiteral("}"); + code << QByteArray(); + + return code.join('\n'); } QT_END_NAMESPACE diff --git a/src/gui/util/qshadergenerator_p.h b/src/gui/util/qshadergenerator_p.h index 7bc8838b52..1f6f9d2532 100644 --- a/src/gui/util/qshadergenerator_p.h +++ b/src/gui/util/qshadergenerator_p.h @@ -54,9 +54,13 @@ #include <QtGui/private/qtguiglobal_p.h> #include <QtGui/private/qshadergraph_p.h> +#include <QtCore/QLoggingCategory> + QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(ShaderGenerator) + class QShaderGenerator { public: |