diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 61705842db..8b0dff31af 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1825,6 +1825,7 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, QStringIterator it(str, str + len); int lastFallback = -1; + char32_t previousUcs4 = 0; while (it.hasNext()) { const char32_t ucs4 = it.peekNext(); @@ -1886,10 +1887,35 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, break; } } + + // For variant-selectors, they are modifiers to the previous character. If we + // end up with different font selections for the selector and the character it + // modifies, we try applying the selector font to the preceding character as well + const int variantSelectorBlock = 0xFE00; + if ((ucs4 & 0xFFF0) == variantSelectorBlock && glyph_pos > 0) { + int selectorFontEngine = glyphs->glyphs[glyph_pos] >> 24; + int precedingCharacterFontEngine = glyphs->glyphs[glyph_pos - 1] >> 24; + + if (selectorFontEngine != precedingCharacterFontEngine) { + QFontEngine *engine = m_engines.at(selectorFontEngine); + glyph_t glyph = engine->glyphIndex(previousUcs4); + if (glyph != 0) { + glyphs->glyphs[glyph_pos - 1] = glyph; + if (!(flags & GlyphIndicesOnly)) { + QGlyphLayout g = glyphs->mid(glyph_pos - 1, 1); + engine->recalcAdvances(&g, flags); + } + + // set the high byte to indicate which engine the glyph came from + glyphs->glyphs[glyph_pos - 1] |= (selectorFontEngine << 24); + } + } + } } it.advance(); ++glyph_pos; + previousUcs4 = ucs4; } *nglyphs = glyph_pos; diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp index b0d6efc065..efd590a730 100644 --- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp +++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp @@ -633,8 +633,12 @@ void tst_QGlyphRun::defaultIgnorables() bool hasFullMainFontRun = false; for (const QGlyphRun &run : runs) { + // QtsSpecialFont will be used for at least five characters: AA[...]111 + // Depending on the font selected for the 0xFE0F variant selector, the + // third 'A' may be in QtsSpecialFont or in the fallback. This is platform-specific, + // so we accept either. if (run.rawFont().familyName() == QStringLiteral("QtsSpecialTestFont") - && run.glyphIndexes().size() == 6) { + && run.glyphIndexes().size() >= 5) { hasFullMainFontRun = true; break; } diff --git a/tests/baseline/painting/scripts/text.qps b/tests/baseline/painting/scripts/text.qps index 4d81b3084c..6bacdfd5e6 100644 --- a/tests/baseline/painting/scripts/text.qps +++ b/tests/baseline/painting/scripts/text.qps @@ -165,7 +165,7 @@ translate 0 75 save setPen black setFont "sansserif" 16 normal - drawText 0 40 "e😃m😇o😍j😜i😸!" + drawText 0 40 "e😃m😇o😍j😜i😸!✈️" restore translate 0 75