summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2020-03-16 18:41:27 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2020-03-16 18:41:27 +0100
commitff922e7b87de147797fbd759167878aec7625f0c (patch)
treea326819f23e2421723f144522f9362ba608d6bb1 /src/gui/text
parente464e1eb8eb63c631fb0916c3ea4540a88d8aad3 (diff)
parent75f52bd0ddc4afbd181c14b310d256e3507052d6 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: src/corelib/kernel/qmetatype.cpp Change-Id: I88eb0d3e9c9a38abf7241a51e370c655ae74e38a
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qharfbuzzng.cpp6
-rw-r--r--src/gui/text/qtextengine.cpp71
-rw-r--r--src/gui/text/qtextlayout.cpp29
3 files changed, 68 insertions, 38 deletions
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 397e6cc49f..4613aff9e8 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -230,6 +230,12 @@ static const hb_script_t _qtscript_to_hbscript[] = {
hb_script_t(HB_TAG('N', 'a', 'n', 'd')), // Script_Nandinagari
hb_script_t(HB_TAG('H', 'm', 'n', 'p')), // Script_NyiakengPuachueHmong
hb_script_t(HB_TAG('W', 'c', 'h', 'o')), // Script_Wancho
+
+ // Unicode 13.0 additions (as above)
+ hb_script_t(HB_TAG('C', 'h', 'o', 'r')), // Script_Chorasmian
+ hb_script_t(HB_TAG('D', 'i', 'v', 'e')), // Script_DivesAkuru
+ hb_script_t(HB_TAG('K', 'h', 'i', 't')), // Script_KhitanSmallScript
+ hb_script_t(HB_TAG('Y', 'e', 'z', 'i')), // Script_Yezidi
};
Q_STATIC_ASSERT(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0]));
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 6a5c443455..f9c4a3949c 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)
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 3d7a097cd9..4d0a9e3a7c 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1667,7 +1667,8 @@ namespace {
QFontEngine *previousGlyphFontEngine;
QFixed minw;
- QFixed softHyphenWidth;
+ QFixed currentSoftHyphenWidth;
+ QFixed commitedSoftHyphenWidth;
QFixed rightBearing;
QFixed minimumRightBearing;
@@ -1681,7 +1682,7 @@ namespace {
QFixed calculateNewWidth(const QScriptLine &line) const {
return line.textWidth + tmpData.textWidth + spaceData.textWidth
- + softHyphenWidth + negativeRightBearing();
+ + (line.textWidth > 0 ? currentSoftHyphenWidth : QFixed()) + negativeRightBearing();
}
inline glyph_t currentGlyph() const
@@ -1755,6 +1756,7 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
return true;
+ const QFixed oldTextWidth = line.textWidth;
minw = qMax(minw, tmpData.textWidth);
line += tmpData;
line.textWidth += spaceData.textWidth;
@@ -1765,6 +1767,11 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
spaceData.textWidth = 0;
spaceData.length = 0;
+ if (oldTextWidth != line.textWidth || currentSoftHyphenWidth > 0) {
+ commitedSoftHyphenWidth = currentSoftHyphenWidth;
+ currentSoftHyphenWidth = 0;
+ }
+
return false;
}
@@ -1837,7 +1844,6 @@ void QTextLine::layout_helper(int maxGlyphs)
while (newItem < eng->layoutData->items.size()) {
lbh.resetRightBearing();
- lbh.softHyphenWidth = 0;
if (newItem != item) {
item = newItem;
const QScriptItem &current = eng->layoutData->items.at(item);
@@ -1975,9 +1981,9 @@ void QTextLine::layout_helper(int maxGlyphs)
} while (lbh.currentPosition < end);
lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
- if (lbh.currentPosition > 0 && lbh.currentPosition < end
- && attributes[lbh.currentPosition].lineBreak
- && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
+ if (lbh.currentPosition > 0 && lbh.currentPosition <= end
+ && (lbh.currentPosition == end || attributes[lbh.currentPosition].lineBreak)
+ && eng->layoutData->string.at(lbh.currentPosition - 1) == QChar::SoftHyphen) {
// if we are splitting up a word because of
// a soft hyphen then we ...
//
@@ -1994,10 +2000,7 @@ void QTextLine::layout_helper(int maxGlyphs)
// want the soft-hyphen to slip into the next line
// and thus become invisible again.
//
- if (line.length)
- lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
- else if (breakany)
- lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
+ lbh.currentSoftHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
}
if (sb_or_ws|breakany) {
@@ -2023,6 +2026,7 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.calculateRightBearing();
if (lbh.checkFullOtherwiseExtend(line)) {
+
// We are too wide to accept the next glyph with its bearing, so we restore the
// right bearing to that of the previous glyph (the one that was already accepted),
// so that the bearing can be be applied to the final width of the text below.
@@ -2031,9 +2035,7 @@ void QTextLine::layout_helper(int maxGlyphs)
else
lbh.calculateRightBearingForPreviousGlyph();
- if (!breakany) {
- line.textWidth += lbh.softHyphenWidth;
- }
+ line.textWidth += lbh.commitedSoftHyphenWidth;
goto found;
}
@@ -2045,6 +2047,7 @@ void QTextLine::layout_helper(int maxGlyphs)
}
LB_DEBUG("reached end of line");
lbh.checkFullOtherwiseExtend(line);
+ line.textWidth += lbh.commitedSoftHyphenWidth;
found:
line.textAdvance = line.textWidth;