diff options
Diffstat (limited to 'src/gui/text/qfont.cpp')
| -rw-r--r-- | src/gui/text/qfont.cpp | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 7ffb688c035..c144820fa24 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -1829,6 +1829,8 @@ bool QFont::operator==(const QFont &f) const */ bool QFont::operator<(const QFont &f) const { + // NB: This operator actually implements greater-than, because it consistently + // swaps LHS (should be *this, but is `f`) and RHS (should be `f`, but is *this) if (f.d == d) return false; // the < operator for fontdefs ignores point sizes. const QFontDef &r1 = f.d->request; @@ -2168,6 +2170,7 @@ QString QFont::key() const \li Style strategy \li Font style \li Font features + \li Variable axes \endlist \sa fromString() @@ -2193,13 +2196,13 @@ 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 + tag.toString() + u'=' + QString::number(value); + 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; } @@ -2214,7 +2217,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) @@ -2232,6 +2235,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 @@ -2244,8 +2265,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; @@ -2254,14 +2274,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()); @@ -2273,6 +2287,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()); @@ -2289,19 +2305,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; } |
