summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2020-03-05 09:26:42 +0100
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2020-03-13 10:17:54 +0100
commit36325f9d86249a4f17f7efbbc1122c462708d909 (patch)
treea39083024132123e5dd56d14d770ad9a31752e47 /src/gui
parent6dbe03c4d15261d0b860d76acaf6d64243213d15 (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.cpp71
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)