diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2018-01-09 08:33:12 +0100 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2018-01-09 12:16:57 +0000 |
commit | 02557c07da2ac251f36cb6bf7f424071c53f8b45 (patch) | |
tree | fe6f3dec3528d7994c54487742b15f33eed0bbcf /src/gui/text/qfontengine.cpp | |
parent | 12687ccfd5a6056ab24a792dbe28f1d5829fd88c (diff) |
Fix ZWJ and ZWNJ when fallback font is in use
When applying fallback fonts to characters that are joined by
ZWJ or ZWNJ, we also have to set the same font for the control
characters, otherwise we will split the text and the necessary
shaping will not take place. This was reported for emojis, but
will probably also happen for Indic scripts where joiners are
used predominately.
[ChangeLog][QtGui][Text] Fixed ZWJ and ZWNJ control characters
when fallback fonts are in use.
Task-number: QTBUG-65519
Change-Id: Ia37233f3319b95af68ae6053c29997eac65448e0
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/text/qfontengine.cpp')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index ebaeb9b49b..29c48da7be 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1905,8 +1905,33 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, int glyph_pos = 0; QStringIterator it(str, str + len); + + int lastFallback = -1; while (it.hasNext()) { const uint ucs4 = it.peekNext(); + + // If we applied a fallback font to previous glyph, and the current is either + // 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 == QChar(0x200d) || ucs4 == QChar(0x200c))) { + QFontEngine *engine = m_engines.at(lastFallback); + glyph_t glyph = engine->glyphIndex(ucs4); + if (glyph != 0) { + glyphs->glyphs[glyph_pos] = glyph; + if (!(flags & GlyphIndicesOnly)) { + QGlyphLayout g = glyphs->mid(glyph_pos, 1); + engine->recalcAdvances(&g, flags); + } + + // set the high byte to indicate which engine the glyph came from + glyphs->glyphs[glyph_pos] |= (lastFallback << 24); + } else { + lastFallback = -1; + } + } else { + lastFallback = -1; + } + if (glyphs->glyphs[glyph_pos] == 0 && ucs4 != QChar::LineSeparator && ucs4 != QChar::LineFeed @@ -1935,6 +1960,9 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout g = glyphs->mid(glyph_pos, 1); engine->recalcAdvances(&g, flags); } + + lastFallback = x; + // set the high byte to indicate which engine the glyph came from glyphs->glyphs[glyph_pos] |= (x << 24); break; |