diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2020-03-05 09:26:42 +0100 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2020-03-13 10:17:54 +0100 |
commit | 36325f9d86249a4f17f7efbbc1122c462708d909 (patch) | |
tree | a39083024132123e5dd56d14d770ad9a31752e47 /src/gui | |
parent | 6dbe03c4d15261d0b860d76acaf6d64243213d15 (diff) |
Hide default-invisible characters when shaping is disabled
When shaping is disabled we also skipped the step which set
dontPrint to true for soft hyphens, line separators, and
similar characters. This caused boxes to appear in text with
e.g. line separators.
There is a minor modification to the code that is moved:
In the case on unshaped text and only the CMAP able is used,
the font engine for the soft hyphen can be a fallback engine,
so we need to also set the correct engine index when changing
the glyph index.
[ChangeLog][QtGui][Text] Fixed an issue with QFont::PreferNoShaping
where boxes would appear in place of unprintable characters.
Fixes: QTBUG-81994
Change-Id: Ifc9f4f89d928475ca0487a92b4480bd5db5918fd
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/text/qtextengine.cpp | 71 |
1 files changed, 46 insertions, 25 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 81ed8fa97a..26e8141184 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1358,6 +1358,37 @@ void QTextEngine::shapeLine(const QScriptLine &line) extern bool qt_useHarfbuzzNG(); // defined in qfontengine.cpp #endif +static void applyVisibilityRules(ushort ucs, QGlyphLayout *glyphs, uint glyphPosition, QFontEngine *fontEngine) +{ + // hide characters that should normally be invisible + switch (ucs) { + case QChar::LineFeed: + case 0x000c: // FormFeed + case QChar::CarriageReturn: + case QChar::LineSeparator: + case QChar::ParagraphSeparator: + glyphs->attributes[glyphPosition].dontPrint = true; + break; + case QChar::SoftHyphen: + if (!fontEngine->symbol) { + // U+00AD [SOFT HYPHEN] is a default ignorable codepoint, + // so we replace its glyph and metrics with ones for + // U+002D [HYPHEN-MINUS] and make it visible if it appears at line-break + const uint engineIndex = glyphs->glyphs[glyphPosition] & 0xff000000; + glyphs->glyphs[glyphPosition] = fontEngine->glyphIndex('-'); + if (Q_LIKELY(glyphs->glyphs[glyphPosition] != 0)) { + glyphs->glyphs[glyphPosition] |= engineIndex; + QGlyphLayout tmp = glyphs->mid(glyphPosition, 1); + fontEngine->recalcAdvances(&tmp, { }); + } + glyphs->attributes[glyphPosition].dontPrint = true; + } + break; + default: + break; + } +} + void QTextEngine::shapeText(int item) const { Q_ASSERT(item < layoutData->items.size()); @@ -1491,6 +1522,20 @@ void QTextEngine::shapeText(int item) const && QChar::isLowSurrogate(string[i + 1])) { ++i; log_clusters[i] = glyph_pos; + + initialGlyphs.attributes[glyph_pos].dontPrint = !QChar::isPrint(QChar::surrogateToUcs4(string[i], string[i + 1])); + } else { + initialGlyphs.attributes[glyph_pos].dontPrint = !QChar::isPrint(string[i]); + } + + if (Q_UNLIKELY(!initialGlyphs.attributes[glyph_pos].dontPrint)) { + QFontEngine *actualFontEngine = fontEngine; + if (actualFontEngine->type() == QFontEngine::Multi) { + const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24; + actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); + } + + applyVisibilityRules(string[i], &initialGlyphs, glyph_pos, actualFontEngine); } } @@ -1702,31 +1747,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, last_glyph_pos = i + glyphs_shaped; last_cluster = cluster; - // hide characters that should normally be invisible - switch (string[item_pos + str_pos]) { - case QChar::LineFeed: - case 0x000c: // FormFeed - case QChar::CarriageReturn: - case QChar::LineSeparator: - case QChar::ParagraphSeparator: - g.attributes[i].dontPrint = true; - break; - case QChar::SoftHyphen: - if (!actualFontEngine->symbol) { - // U+00AD [SOFT HYPHEN] is a default ignorable codepoint, - // so we replace its glyph and metrics with ones for - // U+002D [HYPHEN-MINUS] and make it visible if it appears at line-break - g.glyphs[i] = actualFontEngine->glyphIndex('-'); - if (Q_LIKELY(g.glyphs[i] != 0)) { - QGlyphLayout tmp = g.mid(i, 1); - actualFontEngine->recalcAdvances(&tmp, { }); - } - g.attributes[i].dontPrint = true; - } - break; - default: - break; - } + applyVisibilityRules(string[item_pos + str_pos], &g, i, actualFontEngine); } } while (str_pos < item_length) |