diff options
author | Jiang Jiang <jiang.jiang@nokia.com> | 2011-05-19 08:29:49 (GMT) |
---|---|---|
committer | Jiang Jiang <jiang.jiang@nokia.com> | 2011-05-23 13:55:03 (GMT) |
commit | e5f38bb543696813a70995c90cd5450602c0356c (patch) | |
tree | 05390f3a3507cc999e05c7526333fd9c5e7f879b /src/gui/text/qtextengine.cpp | |
parent | d80949eee06ff464d58bd97a6c89bae7e961f3c8 (diff) | |
download | Qt-e5f38bb543696813a70995c90cd5450602c0356c.zip Qt-e5f38bb543696813a70995c90cd5450602c0356c.tar.gz Qt-e5f38bb543696813a70995c90cd5450602c0356c.tar.bz2 |
Support placing cursor in ligature with mouse or touch
We need to find out the closest element in the ligature to
the point we clicked (or tapped), currently we do this by
dividing the width of that ligature glyph evenly by the number
of characters it covered. We only support Common and Greek script
at this point, ligatures in other scripts are still handled as a
whole.
Task-number: QTBUG-19260
Reviewed-by: Eskil
Diffstat (limited to 'src/gui/text/qtextengine.cpp')
-rw-r--r-- | src/gui/text/qtextengine.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 806779a..62de1fe 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2697,6 +2697,72 @@ QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line) return width(line.from + pos, line.length - pos); } +// Scan in logClusters[from..to-1] for glyph_pos +int QTextEngine::getClusterLength(unsigned short *logClusters, + const HB_CharAttributes *attributes, + int from, int to, int glyph_pos, int *start) +{ + int clusterLength = 0; + for (int i = from; i < to; i++) { + if (logClusters[i] == glyph_pos && attributes[i].charStop) { + if (*start < 0) + *start = i; + clusterLength++; + } + else if (clusterLength) + break; + } + return clusterLength; +} + +int QTextEngine::positionInLigature(const QScriptItem *si, int end, + QFixed x, QFixed edge, int glyph_pos) +{ + unsigned short *logClusters = this->logClusters(si); + int clusterStart = -1; + int clusterLength = 0; + + if (si->analysis.script != QUnicodeTables::Common && + si->analysis.script != QUnicodeTables::Greek) { + if (glyph_pos == -1) + return si->position + end; + else { + int i; + for (i = 0; i < end; i++) + if (logClusters[i] == glyph_pos) + break; + return si->position + i; + } + } + + if (glyph_pos == -1 && end > 0) + glyph_pos = logClusters[end - 1]; + else { + if (x < edge) + glyph_pos--; + } + + const HB_CharAttributes *attrs = attributes(); + clusterLength = getClusterLength(logClusters, attrs, 0, end, glyph_pos, &clusterStart); + + if (clusterLength) { + const QGlyphLayout &glyphs = shapedGlyphs(si); + QFixed glyphWidth = glyphs.effectiveAdvance(glyph_pos); + // the approximate width of each individual element of the ligature + QFixed perItemWidth = glyphWidth / clusterLength; + QFixed left = x > edge ? edge : edge - glyphWidth; + int n = ((x - left) / perItemWidth).floor().toInt(); + QFixed dist = x - left - n * perItemWidth; + int closestItem = dist > (perItemWidth / 2) ? n + 1 : n; + int pos = si->position + clusterStart + closestItem; + // Jump to the next charStop + while (!attrs[pos].charStop && pos < end) + pos++; + return pos; + } + return si->position + end; +} + QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) : QTextEngine(string, f), _layoutData(string, _memory, MemSize) |