From eeb0740f2e06c8f2266448d0092f880336ba9e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 11 Aug 2024 23:23:40 +0200 Subject: [PATCH] QTextHtmlParser: Handle fractional font-size pixel values The CSS spec defines the font-size as being a length, which is a combination of a real number and a unit. This applies to the 'px' unit as well, so by treating px values as integers when parsing we were failing to parse not only '12.5px' but also '12.0px'. The code now uses QMetaType::fromType but then sets the resulting pixel type on the QFont as an integer, as QFont does not support fractional pixel sizes. Other code paths in the CSS parsing machinery use QString::toInt(), either directly or via intValueHelper() or lengthValue(). The font code path can potentially be ported over to these other APIs for consistency, but to keep the patch simple this is left for a follow-up. Pick-to: 6.5 6.2 5.15 Change-Id: I972cfe0f3fa3c785efa18c7593d6a497ff28911c Reviewed-by: Eskil Abrahamsen Blomfeldt (cherry picked from commit 5731e3e185d3a69502b2bc4f1fee48c156b34c3c) Reviewed-by: Qt Cherry-pick Bot --- src/gui/text/qcssparser.cpp | 2 +- .../gui/text/qcssparser/tst_qcssparser.cpp | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 7886d9ba91b..b894f539779 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1157,7 +1157,7 @@ static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAd } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) { s.chop(2); value.variant = s; - if (value.variant.convert(QMetaType::fromType())) { + if (value.variant.convert(QMetaType::fromType())) { font->setPixelSize(qBound(0, value.variant.toInt(), (1 << 24) - 1)); valid = true; } diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp index 2d577198840..61731313317 100644 --- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp +++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp @@ -50,6 +50,8 @@ private slots: void gradient(); void extractFontFamily_data(); void extractFontFamily(); + void extractFontSize_data(); + void extractFontSize(); void extractBorder_data(); void extractBorder(); void noTextDecoration(); @@ -1626,6 +1628,65 @@ void tst_QCssParser::extractFontFamily() QTEST(info.family(), "expectedFamily"); } +void tst_QCssParser::extractFontSize_data() +{ + QTest::addColumn("css"); + QTest::addColumn("expectedPixelSize"); + QTest::addColumn("expectedPointSize"); + QTest::addColumn("expectedPointSizeF"); + + QTest::newRow("integer point size") << "font-size: 12pt" << -1 << 12 << 12.0; + QTest::newRow("float point size round down") << "font-size: 12.3pt" << -1 << 12 << 12.3; + QTest::newRow("float point size midpoint") << "font-size: 12.5pt" << -1 << 13 << 12.5; + QTest::newRow("float point size round up") << "font-size: 12.7pt" << -1 << 13 << 12.7; + + QTest::newRow("integer pixel size") << "font-size: 12px" << 12 << -1 << -1.0; + QTest::newRow("float pixel size round down") << "font-size: 12.3px" << 12 << -1 << -1.0; + QTest::newRow("float pixel size midpoint") << "font-size: 12.5px" << 13 << -1 << -1.0; + QTest::newRow("float pixel size round up") << "font-size: 12.7px" << 13 << -1 << -1.0; + + QTest::newRow("shorthand integer point size") << "font: 12pt Arial" << -1 << 12 << 12.0; + QTest::newRow("shorthand float point size round down") << "font: 12.3pt Arial" << -1 << 12 << 12.3; + QTest::newRow("shorthand float point size midpoint") << "font: 12.5pt Arial" << -1 << 13 << 12.5; + QTest::newRow("shorthand float point size round up") << "font: 12.7pt Arial" << -1 << 13 << 12.7; + + QTest::newRow("shorthand integer pixel size") << "font: 12px Arial" << 12 << -1 << -1.0; + QTest::newRow("shorthand float pixel size round down") << "font: 12.3px Arial" << 12 << -1 << -1.0; + QTest::newRow("shorthand float pixel size midpoint") << "font: 12.5px Arial" << 13 << -1 << -1.0; + QTest::newRow("shorthand float pixel size round up") << "font: 12.7px Arial" << 13 << -1 << -1.0; +} + +void tst_QCssParser::extractFontSize() +{ + QFETCH(QString, css); + css.prepend("dummy {"); + css.append(QLatin1Char('}')); + + QCss::Parser parser(css); + QCss::StyleSheet sheet; + QVERIFY(parser.parse(&sheet)); + + QCOMPARE(sheet.styleRules.size() + sheet.nameIndex.size(), 1); + QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ? + sheet.styleRules.at(0) : *sheet.nameIndex.begin(); + + const QList decls = rule.declarations; + QVERIFY(!decls.isEmpty()); + QCss::ValueExtractor extractor(decls); + + int adjustment = 0; + QFont font; + extractor.extractFont(&font, &adjustment); + + QFETCH(int, expectedPixelSize); + QFETCH(int, expectedPointSize); + QFETCH(qreal, expectedPointSizeF); + + QCOMPARE(font.pixelSize(), expectedPixelSize); + QCOMPARE(font.pointSize(), expectedPointSize); + QCOMPARE(font.pointSizeF(), expectedPointSizeF); +} + void tst_QCssParser::extractBorder_data() { QTest::addColumn("css");