diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 13ae30433c..cfeffdfdcb 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6205,7 +6205,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
         QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
 
         const QGlyphLayout &glyphs = ti.glyphs;
-        int which = glyphs.glyphs[0] >> 24;
+        int which = glyphs.glyphs[0] >> glyphLowerBits;
 
         qreal x = p.x();
         qreal y = p.y();
@@ -6217,7 +6217,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
         int start = 0;
         int end, i;
         for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
-            const int e = glyphs.glyphs[end] >> 24;
+            const int e = glyphs.glyphs[end] >> glyphLowerBits;
             if (e == which)
                 continue;
 
@@ -6227,7 +6227,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
             ti2.width = 0;
             // set the high byte to zero and calc the width
             for (i = start; i < end; ++i) {
-                glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
+                glyphs.glyphs[i] = glyphs.glyphs[i] & glyphLowerBitMask;
                 ti2.width += ti.glyphs.effectiveAdvance(i);
             }
 
@@ -6245,7 +6245,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
                 x += ti2.width.toReal();
 
             // reset the high byte for all glyphs and advance to the next sub-string
-            const int hi = which << 24;
+            const int hi = which << glyphLowerBits;
             for (i = start; i < end; ++i) {
                 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
             }
@@ -6260,7 +6260,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
         ti2.width = 0;
         // set the high byte to zero and calc the width
         for (i = start; i < end; ++i) {
-            glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
+            glyphs.glyphs[i] = glyphs.glyphs[i] & glyphLowerBitMask;
             ti2.width += ti.glyphs.effectiveAdvance(i);
         }
 
@@ -6275,7 +6275,7 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText
                                ti2.flags, ti2.width.toReal(), ti2.charFormat);
 
         // reset the high byte for all glyphs
-        const int hi = which << 24;
+        const int hi = which << glyphLowerBits;
         for (i = start; i < end; ++i)
             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 469810f521..5e9cf816af 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -660,6 +660,7 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
             }
         }
     }
+    qDebug()<< "fallbacksForFamily(" << family << "): " << preferredFallbacks << " ... " << otherFallbacks;
 
     return preferredFallbacks + otherFallbacks;
 }
@@ -694,6 +695,7 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
             --i;
         }
     }
+    qDebug()<< "fallbacksForFamily(" << family << "): " << retList;
 
     db->fallbacksCache.insert(cacheKey, new QStringList(retList));
 
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 72f90ae53b..54993de4ba 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1688,11 +1688,11 @@ QImage QFontEngineBox::alphaMapForGlyph(glyph_t)
 // ------------------------------------------------------------------
 
 uchar QFontEngineMulti::highByte(glyph_t glyph)
-{ return glyph >> 24; }
+{ return glyph >> glyphLowerBits; }
 
 // strip high byte from glyph
 static inline glyph_t stripped(glyph_t glyph)
-{ return glyph & 0x00ffffff; }
+{ return glyph & glyphLowerBitMask; }
 
 QFontEngineMulti::QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies)
     : QFontEngine(Multi),
@@ -1753,6 +1753,8 @@ void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamili
     } else {
         m_engines.resize(m_fallbackFamilies.size() + 1);
     }
+    qDebug() << "----- fallbackFamilies: " << m_fallbackFamilies.size();
+    qDebug() << "----- engines: " << m_engines.size();
 
     m_fallbackFamiliesQueried = true;
 }
@@ -1795,6 +1797,10 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
 
 glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
 {
+    bool ok;
+    int maxEngines = qEnvironmentVariableIntValue("QT_MAX_ENGINES", &ok);
+    if ((!ok) || (maxEngines > glyphMaxEngines))
+        maxEngines = glyphMaxEngines;
     glyph_t glyph = engine(0)->glyphIndex(ucs4);
     if (glyph == 0
             && ucs4 != QChar::LineSeparator
@@ -1803,7 +1809,7 @@ glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
             && ucs4 != QChar::ParagraphSeparator) {
         if (!m_fallbackFamiliesQueried)
             const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
-        for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
+        for (int x = 1, n = qMin(m_engines.size(), maxEngines); x < n; ++x) {
             QFontEngine *engine = m_engines.at(x);
             if (!engine) {
                 if (!shouldLoadFontEngineForCharacter(x, ucs4))
@@ -1818,7 +1824,7 @@ glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
             glyph = engine->glyphIndex(ucs4);
             if (glyph != 0) {
                 // set the high byte to indicate which engine the glyph came from
-                glyph |= (x << 24);
+                glyph |= (x << glyphLowerBits);
                 break;
             }
         }
@@ -1845,6 +1851,7 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
         // ZWJ or ZWNJ, we should also try applying the same fallback font to that, in order
         // to get the correct shaping rules applied.
         if (lastFallback >= 0 && (ucs4 == 0x200d || ucs4 == 0x200c)) {
+            // qDebug() << "lastFallback logic";
             QFontEngine *engine = m_engines.at(lastFallback);
             glyph_t glyph = engine->glyphIndex(ucs4);
             if (glyph != 0) {
@@ -1855,13 +1862,17 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
                 }
 
                 // set the high byte to indicate which engine the glyph came from
-                glyphs->glyphs[glyph_pos] |= (lastFallback << 24);
+                glyphs->glyphs[glyph_pos] |= (lastFallback << glyphLowerBits);
             } else {
                 lastFallback = -1;
             }
         } else {
             lastFallback = -1;
         }
+        bool ok;
+        int maxEngines = qEnvironmentVariableIntValue("QT_MAX_ENGINES", &ok);
+        if ((!ok) || (maxEngines > glyphMaxEngines))
+            maxEngines = glyphMaxEngines;
 
         if (glyphs->glyphs[glyph_pos] == 0
                 && ucs4 != QChar::LineSeparator
@@ -1870,11 +1881,13 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
                 && ucs4 != QChar::ParagraphSeparator) {
             if (!m_fallbackFamiliesQueried)
                 const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
-            for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
+            for (int x = 1, n = qMin(m_engines.size(), maxEngines); x < n; ++x) {
                 QFontEngine *engine = m_engines.at(x);
                 if (!engine) {
+                    // qDebug() << "not engine at " << x;
                     if (!shouldLoadFontEngineForCharacter(x, ucs4))
                         continue;
+                    // qDebug() << "should load engine at " << x << " for character " << ucs4;
                     const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);
                     engine = m_engines.at(x);
                     if (!engine)
@@ -1895,7 +1908,7 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
                     lastFallback = x;
 
                     // set the high byte to indicate which engine the glyph came from
-                    glyphs->glyphs[glyph_pos] |= (x << 24);
+                    glyphs->glyphs[glyph_pos] |= (x << glyphLowerBits);
                     break;
                 }
             }
@@ -1949,7 +1962,7 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
         overall.yoff += gm.yoff;
 
         // reset the high byte for all glyphs
-        const int hi = which << 24;
+        const int hi = which << glyphLowerBits;
         for (i = start; i < end; ++i)
             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 
@@ -1974,7 +1987,7 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
     overall.yoff += gm.yoff;
 
     // reset the high byte for all glyphs
-    const int hi = which << 24;
+    const int hi = which << glyphLowerBits;
     for (i = start; i < end; ++i)
         glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 
@@ -2016,7 +2029,7 @@ void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &gl
             glyphs.glyphs[i] = stripped(glyphs.glyphs[i]);
         engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);
         // reset the high byte for all glyphs and update x and y
-        const int hi = which << 24;
+        const int hi = which << glyphLowerBits;
         for (i = start; i < end; ++i)
             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 
@@ -2042,7 +2055,7 @@ void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &gl
     engine(which)->addOutlineToPath(x, y, glyphs.mid(start, end - start), path, flags);
 
     // reset the high byte for all glyphs
-    const int hi = which << 24;
+    const int hi = which << glyphLowerBits;
     for (i = start; i < end; ++i)
         glyphs.glyphs[i] = hi | glyphs.glyphs[i];
 }
@@ -2068,7 +2081,7 @@ void QFontEngineMulti::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperF
         engine(which)->recalcAdvances(&offs, flags);
 
         // reset the high byte for all glyphs and update x and y
-        const int hi = which << 24;
+        const int hi = which << glyphLowerBits;
         for (i = start; i < end; ++i)
             glyphs->glyphs[i] = hi | glyphs->glyphs[i];
 
@@ -2085,7 +2098,7 @@ void QFontEngineMulti::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperF
     engine(which)->recalcAdvances(&offs, flags);
 
     // reset the high byte for all glyphs
-    const int hi = which << 24;
+    const int hi = which << glyphLowerBits;
     for (i = start; i < end; ++i)
         glyphs->glyphs[i] = hi | glyphs->glyphs[i];
 }
@@ -2111,7 +2124,7 @@ void QFontEngineMulti::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags
         engine(which)->doKerning(&offs, flags);
 
         // reset the high byte for all glyphs and update x and y
-        const int hi = which << 24;
+        const int hi = which << glyphLowerBits;
         for (i = start; i < end; ++i)
             glyphs->glyphs[i] = hi | glyphs->glyphs[i];
 
@@ -2128,7 +2141,7 @@ void QFontEngineMulti::doKerning(QGlyphLayout *glyphs, QFontEngine::ShaperFlags
     engine(which)->doKerning(&offs, flags);
 
     // reset the high byte for all glyphs
-    const int hi = which << 24;
+    const int hi = which << glyphLowerBits;
     for (i = start; i < end; ++i)
         glyphs->glyphs[i] = hi | glyphs->glyphs[i];
 }
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 0f2ee3d334..b541ab8775 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1491,7 +1491,7 @@ void QTextEngine::shapeText(int item) const
     if (fontEngine->type() == QFontEngine::Multi) {
         uint lastEngine = ~0u;
         for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
-            const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24;
+            const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> glyphLowerBits;
             if (lastEngine != engineIdx) {
                 itemBoundaries.append(i);
                 itemBoundaries.append(glyph_pos);
@@ -1748,7 +1748,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
 
         if (Q_UNLIKELY(engineIdx != 0)) {
             for (quint32 i = 0; i < num_glyphs; ++i)
-                g.glyphs[i] |= (engineIdx << 24);
+                g.glyphs[i] |= (engineIdx << glyphLowerBits);
         }
 
         if (!actualFontEngine->supportsHorizontalSubPixelPositions()) {
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 6ae3196963..24cc9d7779 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -87,6 +87,9 @@ class QPainter;
 class QAbstractTextDocumentLayout;
 
 typedef quint32 glyph_t;
+constexpr quint32 glyphLowerBits = 21;
+constexpr glyph_t glyphLowerBitMask = 0x001fffff;
+constexpr quint32 glyphMaxEngines = 1 << (32 - glyphLowerBits);
 
 // this uses the same coordinate system as Qt, but a different one to freetype.
 // * y is usually negative, and is equal to the ascent.
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
index c9f3c3cb81..f5932199fa 100644
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
@@ -826,7 +826,7 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
         }
         FcFontSetDestroy(fontSet);
     }
-//    qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies;
+    qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies;
 
     return fallbackFamilies;
 }
