diff options
Diffstat (limited to 'src/gui/text/qfont.cpp')
| -rw-r--r-- | src/gui/text/qfont.cpp | 113 |
1 files changed, 60 insertions, 53 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 2b2f2a27fcd..ba49d538c2c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -31,6 +31,7 @@ #include <QtCore/QMutexLocker> #include <QtCore/QMutex> +#include <algorithm> #include <array> // #define QFONTCACHE_DEBUG @@ -1853,35 +1854,13 @@ bool QFont::operator<(const QFont &f) const int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning; if (f1attrs != f2attrs) return f1attrs < f2attrs; - if (d->features.size() != f.d->features.size()) - return f.d->features.size() < d->features.size(); - - { - auto it = d->features.constBegin(); - auto jt = f.d->features.constBegin(); - for (; it != d->features.constEnd(); ++it, ++jt) { - if (it.key() != jt.key()) - return jt.key() < it.key(); - if (it.value() != jt.value()) - return jt.value() < it.value(); - } + if (d->features != f.d->features) { + return std::lexicographical_compare(f.d->features.keyValueBegin(), f.d->features.keyValueEnd(), + d->features.keyValueBegin(), d->features.keyValueEnd()); } - if (r1.variableAxisValues.size() != r2.variableAxisValues.size()) - return r1.variableAxisValues.size() < r2.variableAxisValues.size(); - - { - auto it = r1.variableAxisValues.constBegin(); - auto jt = r2.variableAxisValues.constBegin(); - for (; it != r1.variableAxisValues.constEnd(); ++it, ++jt) { - if (it.key() != jt.key()) - return jt.key() < it.key(); - if (it.value() != jt.value()) - return jt.value() < it.value(); - } - } - - return false; + return std::lexicographical_compare(r1.variableAxisValues.keyValueBegin(), r1.variableAxisValues.keyValueEnd(), + r2.variableAxisValues.keyValueBegin(), r2.variableAxisValues.keyValueEnd()); } @@ -2170,6 +2149,7 @@ QString QFont::key() const \li Style strategy \li Font style \li Font features + \li Variable axes \endlist \sa fromString() @@ -2195,12 +2175,12 @@ QString QFont::toString() const QString::number((int)styleStrategy()) + comma + styleName(); - QMap<Tag, quint32> sortedFeatures; + fontDescription += comma + QString::number(d->features.size()); for (const auto &[tag, value] : std::as_const(d->features).asKeyValueRange()) - sortedFeatures.insert(tag, value); + fontDescription += comma + QLatin1StringView{tag.toString()} + u'=' + QString::number(value); - fontDescription += comma + QString::number(sortedFeatures.size()); - for (const auto &[tag, value] : std::as_const(sortedFeatures).asKeyValueRange()) + fontDescription += comma + QString::number(d->request.variableAxisValues.size()); + for (const auto &[tag, value] : std::as_const(d->request.variableAxisValues).asKeyValueRange()) fontDescription += comma + QLatin1StringView{tag.toString()} + u'=' + QString::number(value); return fontDescription; @@ -2216,7 +2196,7 @@ size_t qHash(const QFont &font, size_t seed) noexcept return qHash(QFontPrivate::get(font)->request, seed); } -static std::optional<std::pair<QFont::Tag, quint32>> tagAndValueFromString(QStringView view) +static std::optional<std::pair<QFont::Tag, quint32>> fontFeatureFromString(QStringView view) { const int separator = view.indexOf(u'='); if (separator == -1) @@ -2234,6 +2214,24 @@ static std::optional<std::pair<QFont::Tag, quint32>> tagAndValueFromString(QStri return std::make_pair(*tag, value); } +static std::optional<std::pair<QFont::Tag, float>> variableAxisFromString(QStringView view) +{ + const int separator = view.indexOf(u'='); + if (separator == -1) + return std::nullopt; + + const std::optional<QFont::Tag> tag = QFont::Tag::fromString(view.sliced(0, separator)); + if (!tag) + return std::nullopt; + + bool valueOk = false; + const float value = view.sliced(separator + 1).toFloat(&valueOk); + if (!valueOk) + return std::nullopt; + + return std::make_pair(*tag, value); +} + /*! Sets this font to match the description \a descrip. The description is a comma-separated list of the font attributes, as returned by @@ -2246,8 +2244,7 @@ bool QFont::fromString(const QString &descrip) const auto sr = QStringView(descrip).trimmed(); const auto l = sr.split(u','); const int count = l.size(); - if (!count || (count > 2 && count < 9) || count == 9 || - l.first().isEmpty()) { + if (!count || (count > 2 && count < 10) || l.first().isEmpty()) { qWarning("QFont::fromString: Invalid description '%s'", descrip.isEmpty() ? "(empty)" : descrip.toLatin1().data()); return false; @@ -2256,14 +2253,8 @@ bool QFont::fromString(const QString &descrip) setFamily(l[0].toString()); if (count > 1 && l[1].toDouble() > 0.0) setPointSizeF(l[1].toDouble()); - if (count == 9) { - setStyleHint((StyleHint) l[2].toInt()); - setWeight(QFont::Weight(l[3].toInt())); - setItalic(l[4].toInt()); - setUnderline(l[5].toInt()); - setStrikeOut(l[6].toInt()); - setFixedPitch(l[7].toInt()); - } else if (count >= 10) { + + if (count >= 10) { if (l[2].toInt() > 0) setPixelSize(l[2].toInt()); setStyleHint((StyleHint) l[3].toInt()); @@ -2275,6 +2266,8 @@ bool QFont::fromString(const QString &descrip) setUnderline(l[6].toInt()); setStrikeOut(l[7].toInt()); setFixedPitch(l[8].toInt()); + if (!d->request.fixedPitch) // assume 'false' fixedPitch equals default + d->request.ignorePitch = true; if (count >= 16) { setCapitalization((Capitalization)l[10].toInt()); setLetterSpacing((SpacingType)l[11].toInt(), l[12].toDouble()); @@ -2291,19 +2284,33 @@ bool QFont::fromString(const QString &descrip) d->request.styleName.clear(); clearFeatures(); - if (count >= 18) { - const int featureCount = l[17].toInt(); - if (count >= featureCount + 18) { - for (int i = 0; i < featureCount; ++i) { - if (const auto feature = tagAndValueFromString(l[18 + i])) - setFeature(feature->first, feature->second); - } - } + clearVariableAxes(); + + int position = 17; + if (position >= count) + return true; + + const int featureCount = l[position++].toInt(); + if (position + featureCount > count) + return true; + + for (int i = 0; i < featureCount; ++i) { + if (const auto feature = fontFeatureFromString(l[position++])) + setFeature(feature->first, feature->second); } - } - if (count >= 9 && !d->request.fixedPitch) // assume 'false' fixedPitch equals default - d->request.ignorePitch = true; + if (position >= count) + return true; + + const int variableAxisCount = l[position++].toInt(); + if (position + variableAxisCount > count) + return true; + + for (int i = 0; i < variableAxisCount; ++i) { + if (const auto axis = variableAxisFromString(l[position++])) + setVariableAxis(axis->first, axis->second); + } + } return true; } |
