summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/text
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-08-24 13:25:19 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-09-29 18:06:40 +0200
commit1fe7144a0746353ea629cd91b5c0d04a8434159b (patch)
treef0521c73e7a233920e09d133e7a92f0e69aee468 /tests/auto/gui/text
parent87cabd0b92bc348f73be2fe0a20a57fa485f6665 (diff)
Introduce QGlyphRun::stringIndexes()
This introduces a way to trace each entry in the glyph index array to a specific index in the original text passed to QTextLayout, as well as a convenience function to access the original string from the QGlyphRun. The index information is stored in the logClusters array internally in Qt, but it contains the inverse information: For each character in the output string, it contains an index into the glyph array. In order to get the string indexes for each glyph, which makes a lot more sense in the context of the QGlyphRun API, we need to do a little search to construct the data. To avoid adding unnecessary allocations, we make the new APIs opt-in. If you do not specify anything, you will only get the glyph indexes and glyph positions as before. However, you can now specify exactly which parts of the layout to extract using an optional flags parameter. This also adds a manual test which can be very handy to visualize QTextLayouts and how they are split into QGlyphRuns. Fixes: QTBUG-103932 Change-Id: Ie4288fff338b9482aba0aba29fc7e1e59fa60900 Reviewed-by: Lars Knoll <lars@knoll.priv.no>
Diffstat (limited to 'tests/auto/gui/text')
-rw-r--r--tests/auto/gui/text/qglyphrun/CMakeLists.txt1
-rw-r--r--tests/auto/gui/text/qglyphrun/Ligatures.otfbin0 -> 24624 bytes
-rw-r--r--tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp310
3 files changed, 311 insertions, 0 deletions
diff --git a/tests/auto/gui/text/qglyphrun/CMakeLists.txt b/tests/auto/gui/text/qglyphrun/CMakeLists.txt
index 4928b1c0d4..d6040ba625 100644
--- a/tests/auto/gui/text/qglyphrun/CMakeLists.txt
+++ b/tests/auto/gui/text/qglyphrun/CMakeLists.txt
@@ -13,6 +13,7 @@ set_source_files_properties("../../../shared/resources/test.ttf"
)
set(testdata_resource_files
"../../../shared/resources/test.ttf"
+ "Ligatures.otf"
)
qt_internal_add_test(tst_qglyphrun
diff --git a/tests/auto/gui/text/qglyphrun/Ligatures.otf b/tests/auto/gui/text/qglyphrun/Ligatures.otf
new file mode 100644
index 0000000000..194218a0f6
--- /dev/null
+++ b/tests/auto/gui/text/qglyphrun/Ligatures.otf
Binary files differ
diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
index 1569a4bf84..9fbc2bebc0 100644
--- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
+++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
@@ -39,6 +39,9 @@ private slots:
void mixedScripts();
void multiLineBoundingRect();
void defaultIgnorables();
+ void stringIndexes();
+ void retrievalFlags_data();
+ void retrievalFlags();
private:
int m_testFontId;
@@ -618,6 +621,313 @@ void tst_QGlyphRun::defaultIgnorables()
QCOMPARE(runs.at(0).glyphIndexes()[0], uint(0));
}
+void tst_QGlyphRun::stringIndexes()
+{
+ int ligatureFontId = QFontDatabase::addApplicationFont(QFINDTESTDATA("Ligatures.otf"));
+ QVERIFY(ligatureFontId >= 0);
+
+ QFont ligatureFont = QFont("QtLigatures");
+ QCOMPARE(QFontInfo(ligatureFont).family(), QString::fromLatin1("QtLigatures"));
+
+ QTextLayout::GlyphRunRetrievalFlags retrievalFlags
+ = QTextLayout::RetrieveGlyphIndexes | QTextLayout::RetrieveStringIndexes;
+
+ // Three characters -> three glyphs
+ {
+ QTextLayout layout;
+ layout.setText("f i");
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 3);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 2);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(2, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 1);
+ QCOMPARE(stringIndexes.at(0), 2);
+ }
+ }
+
+ // Two characters -> one glyph
+ {
+ QTextLayout layout;
+ layout.setText("fi");
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 1);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 233);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 1);
+ QCOMPARE(stringIndexes.at(0), 0);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 1);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 233);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 1);
+ QCOMPARE(stringIndexes.at(0), 1);
+ }
+ }
+
+ // Four characters -> three glyphs
+ {
+ QTextLayout layout;
+ layout.setText("ffii");
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 3);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 71);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 233);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(2), 74);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 3);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 3);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(1, 1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 1);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 233);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 1);
+ QCOMPARE(stringIndexes.at(0), 1);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(1, 2, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 1);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 233);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 1);
+ QCOMPARE(stringIndexes.at(0), 1);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(1, 3, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 2);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 233);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 74);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 2);
+ QCOMPARE(stringIndexes.at(0), 1);
+ QCOMPARE(stringIndexes.at(1), 3);
+ }
+
+ }
+
+ // One character -> two glyphs
+ {
+ QTextLayout layout;
+ layout.setText(QChar(0xe6)); // LATIN SMALL LETTER AE
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 2);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 66);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 70);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 2);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 0);
+ }
+
+ // Three characters -> four glyphs
+ {
+ QTextLayout layout;
+ layout.setText(QString('f') + QChar(0xe6) + QChar('i'));
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 4);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 71);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 66);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(2), 70);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(3), 74);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 4);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 1);
+ QCOMPARE(stringIndexes.at(3), 2);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 3);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 66);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 70);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(2), 74);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 3);
+ QCOMPARE(stringIndexes.at(0), 1);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 2);
+ }
+
+ {
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(0, 2, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 3);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 71);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 66);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(2), 70);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 3);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 1);
+ }
+
+
+ }
+
+ // Five characters -> five glyphs
+ {
+ QTextLayout layout;
+ layout.setText(QLatin1String("ffi") + QChar(0xe6) + QLatin1Char('i'));
+ layout.setFont(ligatureFont);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, retrievalFlags);
+ QCOMPARE(glyphRuns.size(), 1);
+
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().size(), 5);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(0), 71);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(1), 233);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(2), 66);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(3), 70);
+ QCOMPARE(glyphRuns.at(0).glyphIndexes().at(4), 74);
+
+ QList<qsizetype> stringIndexes = glyphRuns.at(0).stringIndexes();
+ QCOMPARE(stringIndexes.size(), 5);
+ QCOMPARE(stringIndexes.at(0), 0);
+ QCOMPARE(stringIndexes.at(1), 1);
+ QCOMPARE(stringIndexes.at(2), 3);
+ QCOMPARE(stringIndexes.at(3), 3);
+ QCOMPARE(stringIndexes.at(4), 4);
+ }
+
+}
+
+void tst_QGlyphRun::retrievalFlags_data()
+{
+ QTest::addColumn<QTextLayout::GlyphRunRetrievalFlags>("flags");
+ QTest::addColumn<bool>("expectedGlyphIndexes");
+ QTest::addColumn<bool>("expectedStringIndexes");
+ QTest::addColumn<bool>("expectedString");
+ QTest::addColumn<bool>("expectedGlyphPositions");
+
+ QTest::newRow("Glyph indexes")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::RetrieveGlyphIndexes)
+ << true << false << false << false;
+ QTest::newRow("Glyph Positions")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::RetrieveGlyphPositions)
+ << false << false << false << true;
+ QTest::newRow("String indexes")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::RetrieveStringIndexes)
+ << false << true << false << false;
+ QTest::newRow("String")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::RetrieveString)
+ << false << false << true << false;
+
+ QTest::newRow("Default")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::DefaultRetrievalFlags)
+ << true << false << false << true;
+ QTest::newRow("All")
+ << QTextLayout::GlyphRunRetrievalFlags(QTextLayout::RetrieveAll)
+ << true << true << true << true;
+}
+
+void tst_QGlyphRun::retrievalFlags()
+{
+ QFETCH(QTextLayout::GlyphRunRetrievalFlags, flags);
+ QFETCH(bool, expectedGlyphIndexes);
+ QFETCH(bool, expectedStringIndexes);
+ QFETCH(bool, expectedString);
+ QFETCH(bool, expectedGlyphPositions);
+
+ QTextLayout layout;
+ layout.setText(QLatin1String("abc"));
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> glyphRuns = layout.glyphRuns(-1, -1, flags);
+ QVERIFY(!glyphRuns.isEmpty());
+
+ QGlyphRun firstGlyphRun = glyphRuns.first();
+ QCOMPARE(firstGlyphRun.glyphIndexes().isEmpty(), !expectedGlyphIndexes);
+ QCOMPARE(firstGlyphRun.stringIndexes().isEmpty(), !expectedStringIndexes);
+ QCOMPARE(firstGlyphRun.sourceString().isEmpty(), !expectedString);
+ QCOMPARE(firstGlyphRun.positions().isEmpty(), !expectedGlyphPositions);
+}
+
#endif // QT_NO_RAWFONT
QTEST_MAIN(tst_QGlyphRun)