diff options
author | Igor Khanin <[email protected]> | 2024-07-12 21:20:01 +0300 |
---|---|---|
committer | Igor Khanin <[email protected]> | 2024-10-10 18:36:58 +0300 |
commit | 889bdf1de48ecd7ae313c0b400e3a971f496e041 (patch) | |
tree | 02a482aed67a28a8f77000a08cd8ae4a354cbba1 | |
parent | 38bb72720aef4caf3de6c1c68ab46435d7c8d65c (diff) |
QTextOption: Add flag for showing default ignorable characters
The presence of the flag instructs the text shaping engine to not
outright ignore normally non-printable code points, so that if the font
has glyphs for them, they will be rendered. This is useful when editing
plain text whose layout is affected by the presence of such characters
(primarily BiDi control characters), and for layout debugging in
general.
[ChangeLog][QtGui][Text] Added QTextOption::ShowDefaultIgnorables flag.
Change-Id: I610a30603f718254ab8e532083e65252351159f0
Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]>
Reviewed-by: Christian Ehrlicher <[email protected]>
-rw-r--r-- | src/gui/text/qtextengine.cpp | 10 | ||||
-rw-r--r-- | src/gui/text/qtextoption.cpp | 1 | ||||
-rw-r--r-- | src/gui/text/qtextoption.h | 1 | ||||
-rw-r--r-- | tests/auto/gui/text/qfontmetrics/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp | 57 | ||||
-rw-r--r-- | tests/auto/shared/resources/testfont_bidimarks.ttf | bin | 0 -> 66536 bytes |
6 files changed, 70 insertions, 3 deletions
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::Tab> 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<bool>("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 Binary files differnew file mode 100644 index 00000000000..a698930cfa8 --- /dev/null +++ b/tests/auto/shared/resources/testfont_bidimarks.ttf |