diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 08512bead57..e3af305760e 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1498,16 +1498,20 @@ void QTextEngine::shapeText(int item) const for (int i = 0; i < itemLength; ++i, ++glyph_pos) { log_clusters[i] = glyph_pos; initialGlyphs.attributes[glyph_pos].clusterStart = true; + + bool is_print_char; if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1])) { - initialGlyphs.attributes[glyph_pos].dontPrint = !QChar::isPrint(QChar::surrogateToUcs4(string[i], string[i + 1])); + is_print_char = QChar::isPrint(QChar::surrogateToUcs4(string[i], string[i + 1])); ++i; log_clusters[i] = glyph_pos; } else { - initialGlyphs.attributes[glyph_pos].dontPrint = !QChar::isPrint(string[i]); + is_print_char = QChar::isPrint(string[i]); } + initialGlyphs.attributes[glyph_pos].dontPrint = + !is_print_char && !(option.flags() & QTextOption::ShowDefaultIgnorables); if (Q_UNLIKELY(!initialGlyphs.attributes[glyph_pos].dontPrint)) { QFontEngine *actualFontEngine = fontEngine; @@ -1638,7 +1642,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, uint buffer_flags = HB_BUFFER_FLAG_DEFAULT; // Symbol encoding used to encode various crap in the 32..255 character code range, // and thus might override U+00AD [SHY]; avoid hiding default ignorables - if (Q_UNLIKELY(actualFontEngine->symbol)) + if (Q_UNLIKELY(actualFontEngine->symbol || (option.flags() & QTextOption::ShowDefaultIgnorables))) buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES; hb_buffer_set_flags(buffer, hb_buffer_flags_t(buffer_flags)); diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index ea1b556f081..a94fe32490e 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -268,6 +268,7 @@ QList QTextOption::tabs() const shown differently to breaking spaces. \value ShowLineAndParagraphSeparators Visualize line and paragraph separators with appropriate symbol characters. \value [since 5.7] ShowDocumentTerminator Visualize the end of the document with a section sign. + \value [since 6.9] ShowDefaultIgnorables Render normally non-visual characters if supported by font. \value AddSpaceForLineAndParagraphSeparators While determining the line-break positions take into account the space added for drawing a separator character. \value SuppressColors Suppress all color changes in the character formats (except the main selection). diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h index f0a385ff50f..88dd6959dc3 100644 --- a/src/gui/text/qtextoption.h +++ b/src/gui/text/qtextoption.h @@ -73,6 +73,7 @@ public: AddSpaceForLineAndParagraphSeparators = 0x4, SuppressColors = 0x8, ShowDocumentTerminator = 0x10, + ShowDefaultIgnorables = 0x20, IncludeTrailingSpaces = 0x80000000, }; Q_DECLARE_FLAGS(Flags, Flag) diff --git a/tests/auto/gui/text/qfontmetrics/CMakeLists.txt b/tests/auto/gui/text/qfontmetrics/CMakeLists.txt index ee2f76ef76a..e00593c7089 100644 --- a/tests/auto/gui/text/qfontmetrics/CMakeLists.txt +++ b/tests/auto/gui/text/qfontmetrics/CMakeLists.txt @@ -27,9 +27,13 @@ set_source_files_properties("../../../shared/resources/testfont.ttf" set_source_files_properties("../../../shared/resources/testfont_linemetrics.otf" PROPERTIES QT_RESOURCE_ALIAS "testfont_linemetrics.otf" ) +set_source_files_properties("../../../shared/resources/testfont_bidimarks.ttf" + PROPERTIES QT_RESOURCE_ALIAS "testfont_bidimarks.ttf" +) set(testfont_resource_files "../../../shared/resources/testfont.ttf" "../../../shared/resources/testfont_linemetrics.otf" + "../../../shared/resources/testfont_bidimarks.ttf" "ucs4font.ttf" ) diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp index bad33ab0a47..429eab131a6 100644 --- a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp +++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp @@ -37,6 +37,8 @@ private slots: void largeText_data(); void largeText(); // QTBUG-123339 void typoLineMetrics(); + void defaultIgnorableHorizontalAdvance_data(); + void defaultIgnorableHorizontalAdvance(); }; void tst_QFontMetrics::same() @@ -454,5 +456,60 @@ void tst_QFontMetrics::typoLineMetrics() } } +void tst_QFontMetrics::defaultIgnorableHorizontalAdvance_data() +{ + QTest::addColumn("withShaping"); + + QTest::newRow("With Text Shaping") << true; + QTest::newRow("Without Text Shaping") << false; +} + +void tst_QFontMetrics::defaultIgnorableHorizontalAdvance() +{ + QFETCH(bool, withShaping); + + // testfont_bidimarks.ttf is a version of testfont.ttf with additional + // glyphs for U+200E (LRM) and U+200F (RLM) + QString testFont = QFINDTESTDATA("fonts/testfont_bidimarks.ttf"); + QVERIFY(!testFont.isEmpty()); + + int id = QFontDatabase::addApplicationFont(testFont); + QVERIFY(id >= 0); + + auto cleanup = qScopeGuard([&id] { + if (id >= 0) + QFontDatabase::removeApplicationFont(id); + }); + + QFont withoutSupport; + QFont withSupport(QFontDatabase::applicationFontFamilies(id).at(0)); + + if (!withShaping) { + withoutSupport.setStyleStrategy(QFont::PreferNoShaping); + withSupport.setStyleStrategy(QFont::PreferNoShaping); + } + + QFontMetrics withoutSupportMetrics(withoutSupport); + QFontMetrics withSupportMetrics(withSupport); + + QTextOption opt; + opt.setFlags(QTextOption::ShowDefaultIgnorables); + + const QChar LRM = (ushort)0x200e; + const QString str = QStringLiteral("[") + LRM + QStringLiteral("]"); + + int withoutSupportWithoutIgnorablesAdvance = withoutSupportMetrics.horizontalAdvance(str); + int withoutSupportWithIgnorablesAdvance = withoutSupportMetrics.horizontalAdvance(str, opt); + + QCOMPARE_GT(withoutSupportWithoutIgnorablesAdvance, 0); + QCOMPARE_EQ(withoutSupportWithIgnorablesAdvance, withoutSupportWithoutIgnorablesAdvance); + + int withSupportWithoutIgnorablesAdvance = withSupportMetrics.horizontalAdvance(str); + int withSupportWithIgnorablesAdvance = withSupportMetrics.horizontalAdvance(str, opt); + + QCOMPARE_GT(withSupportWithoutIgnorablesAdvance, 0); + QCOMPARE_GT(withSupportWithIgnorablesAdvance, withSupportWithoutIgnorablesAdvance); +} + QTEST_MAIN(tst_QFontMetrics) #include "tst_qfontmetrics.moc" diff --git a/tests/auto/shared/resources/testfont_bidimarks.ttf b/tests/auto/shared/resources/testfont_bidimarks.ttf new file mode 100644 index 00000000000..a698930cfa8 Binary files /dev/null and b/tests/auto/shared/resources/testfont_bidimarks.ttf differ