summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Khanin <[email protected]>2024-07-12 21:20:01 +0300
committerIgor Khanin <[email protected]>2024-10-10 18:36:58 +0300
commit889bdf1de48ecd7ae313c0b400e3a971f496e041 (patch)
tree02a482aed67a28a8f77000a08cd8ae4a354cbba1
parent38bb72720aef4caf3de6c1c68ab46435d7c8d65c (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.cpp10
-rw-r--r--src/gui/text/qtextoption.cpp1
-rw-r--r--src/gui/text/qtextoption.h1
-rw-r--r--tests/auto/gui/text/qfontmetrics/CMakeLists.txt4
-rw-r--r--tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp57
-rw-r--r--tests/auto/shared/resources/testfont_bidimarks.ttfbin0 -> 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
new file mode 100644
index 00000000000..a698930cfa8
--- /dev/null
+++ b/tests/auto/shared/resources/testfont_bidimarks.ttf
Binary files differ