From 1dd9a0af4f577ccb5578cea562a98686c8e290e6 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Date: Wed, 9 Jul 2014 09:49:59 +0200
Subject: [PATCH] Fix fallbacks for adapted common script

When the platform plugin gives us specific fallbacks for a
specific script, we need to respect this, and load the correct
font family regardless of which writing systems it supports.

This is especially important since the common script is adapted
to match surrounding, proper scripts, so characters such as
digits next to e.g. Hebrew text will be marked as Hebrew. On
stock Android, there is a single Hebrew font, and this would
previously be put in all fallback slots for Hebrew regardless of
what fallback fonts were dictated by the platform plugin. Since
this font does not support the digits, they would show up as boxes.

[ChangeLog][Android] Fixed common characters like digits and
punctuation showing as boxes when positioned next to non-latin
scripts.

Task-number: QTBUG-39377
Change-Id: I1555e208a8ddc587c0bbdbfff1600cafdd9442e9
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
---
 src/gui/text/qfontdatabase.cpp                | 10 ++++----
 src/gui/text/qfontdatabase.h                  |  2 +-
 src/gui/text/qfontengine_qpa.cpp              |  2 +-
 .../gui/text/qfontdatabase/qfontdatabase.pro  |  5 ++++
 .../auto/gui/text/qfontdatabase/testdata.qrc  |  5 ++++
 .../text/qfontdatabase/tst_qfontdatabase.cpp  | 24 +++++++++++++++++++
 6 files changed, 41 insertions(+), 7 deletions(-)
 create mode 100644 tests/auto/gui/text/qfontdatabase/testdata.qrc

diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 06438103ad6..86a0bf10663 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -596,7 +596,7 @@ struct QtFontDesc
 
 static int match(int script, const QFontDef &request,
                  const QString &family_name, const QString &foundry_name, int force_encoding_id,
-                 QtFontDesc *desc, const QList<int> &blacklisted);
+                 QtFontDesc *desc, const QList<int> &blacklisted, bool fallback);
 
 static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi)
 {
@@ -1079,7 +1079,7 @@ static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
 */
 static int match(int script, const QFontDef &request,
                  const QString &family_name, const QString &foundry_name, int force_encoding_id,
-                 QtFontDesc *desc, const QList<int> &blacklistedFamilies)
+                 QtFontDesc *desc, const QList<int> &blacklistedFamilies, bool fallback = false)
 {
     Q_UNUSED(force_encoding_id);
     int result = -1;
@@ -1132,7 +1132,7 @@ static int match(int script, const QFontDef &request,
             load(test.family->name, script);
 
         // Check if family is supported in the script we want
-        if (script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported))
+        if (!fallback && script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported))
             continue;
 
         // as we know the script is supported, we can be sure
@@ -2450,7 +2450,7 @@ bool QFontDatabase::supportsThreadedFontRendering()
 */
 QFontEngine *
 QFontDatabase::findFont(int script, const QFontPrivate *fp,
-                        const QFontDef &request, bool multi)
+                        const QFontDef &request, bool multi, bool fallback)
 {
     QMutexLocker locker(fontDatabaseMutex());
 
@@ -2478,7 +2478,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
 
     QtFontDesc desc;
     QList<int> blackListed;
-    int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed);
+    int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed, fallback);
     if (index >= 0) {
         engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
         if (!engine)
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 9986ef6c606..833e5747071 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -160,7 +160,7 @@ private:
     static void createDatabase();
     static void parseFontName(const QString &name, QString &foundry, QString &family);
     static QString resolveFontFamilyAlias(const QString &family);
-    static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false);
+    static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false, bool fallback = false);
     static void load(const QFontPrivate *d, int script);
 
     friend struct QFontDef;
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp
index f9ed3c38c16..a115d2a9012 100644
--- a/src/gui/text/qfontengine_qpa.cpp
+++ b/src/gui/text/qfontengine_qpa.cpp
@@ -663,7 +663,7 @@ void QFontEngineMultiQPA::loadEngine(int at)
     request.family = fallbackFamilies.at(at-1);
     engines[at] = QFontDatabase::findFont(script,
                                           /*fontprivate = */0,
-                                          request, /*multi = */false);
+                                          request, /*multi = */false, true);
     Q_ASSERT(engines[at]);
     engines[at]->ref.ref();
     engines[at]->fontDef = request;
diff --git a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
index 6975c4088b9..831ed1f572f 100644
--- a/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
+++ b/tests/auto/gui/text/qfontdatabase/qfontdatabase.pro
@@ -9,3 +9,8 @@ wince* {
     additionalFiles.path = .
     DEPLOYMENT += additionalFiles
 }
+
+android {
+    RESOURCES += testdata.qrc
+}
+
diff --git a/tests/auto/gui/text/qfontdatabase/testdata.qrc b/tests/auto/gui/text/qfontdatabase/testdata.qrc
new file mode 100644
index 00000000000..8a8670bf173
--- /dev/null
+++ b/tests/auto/gui/text/qfontdatabase/testdata.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>LED_REAL.TTF</file>
+    </qresource>
+</RCC>
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 28db0ba2911..2ae12ec2465 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -44,6 +44,8 @@
 #include <qfontdatabase.h>
 #include <qfontinfo.h>
 #include <qfontmetrics.h>
+#include <qtextlayout.h>
+#include <private/qrawfont_p.h>
 #include <qpa/qplatformfontdatabase.h>
 
 class tst_QFontDatabase : public QObject
@@ -77,6 +79,7 @@ private slots:
     void addAppFont();
 
     void aliases();
+    void fallbackFonts();
 
 private:
     const QString m_testFont;
@@ -285,5 +288,26 @@ void tst_QFontDatabase::aliases()
     QVERIFY(db.hasFamily(alias));
 }
 
+void tst_QFontDatabase::fallbackFonts()
+{
+    QTextLayout layout;
+    QString s;
+    s.append(QChar(0x31));
+    s.append(QChar(0x05D0));
+    layout.setText(s);
+    layout.beginLayout();
+    layout.createLine();
+    layout.endLayout();
+
+    QList<QGlyphRun> runs = layout.glyphRuns(0, 1);
+    foreach (QGlyphRun run, runs) {
+        QRawFont rawFont = run.rawFont();
+        QVERIFY(rawFont.isValid());
+
+        QCOMPARE(run.glyphIndexes().size(), 1);
+        QVERIFY(run.glyphIndexes().at(0) != 0);
+    }
+}
+
 QTEST_MAIN(tst_QFontDatabase)
 #include "tst_qfontdatabase.moc"
-- 
GitLab