From 23e559473594b4d671405923ecd07d0f04047239 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 12 Oct 2011 08:25:45 +0200 Subject: Add QGlyphRun::SplitLigature flag If the glyph run is generated based on characters which split a ligature glyph, it needs to include the ligature glyph in the run, and when painting, we need to clip the painter to the reported bounding rect of the run in order to avoid painting too much of the ligature. To make it possible to reduce clipping to a minimum, we need a flag to inform of whether the glyph run contains a split ligature or not. Change-Id: Id787e0bec6d6e8e06cc818700ae0fca22cf81e98 Reviewed-by: Jiang Jiang --- src/gui/text/qglyphrun.cpp | 8 ++++++ src/gui/text/qglyphrun.h | 9 ++++--- src/gui/text/qtextlayout.cpp | 60 ++++++++++++++++++++++++++------------------ 3 files changed, 49 insertions(+), 28 deletions(-) (limited to 'src/gui') diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp index a4e9048678..0457202a18 100644 --- a/src/gui/text/qglyphrun.cpp +++ b/src/gui/text/qglyphrun.cpp @@ -100,6 +100,14 @@ QT_BEGIN_NAMESPACE \value RightToLeft Indicates that the glyphs are ordered right to left. This can affect the positioning of other screen elements that are relative to the glyph run, such as an inline text object. + \value SplitLigature Indicates that the glyph run splits a ligature glyph. This means + that a ligature glyph is included in the run, but the characters represented by it corresponds + only to part of that ligature. The glyph run's boundingRect() function can in this case be used + to retrieve the area covered by glyphs that correspond to the characters represented by the + glyph run. When visualizing the glyphs, care needs to be taken to clip to this bounding rect to + ensure that only the corresponding part of the ligature is painted. In particular, this can be + the case when retrieving a glyph run from a QTextLayout for a specific character range, e.g. + when retrieving the selected area of a QTextLayout. */ /*! diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index 5a55eacbcb..22fb5ff395 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -60,10 +60,11 @@ class Q_GUI_EXPORT QGlyphRun { public: enum GlyphRunFlag { - Overline = 0x1, - Underline = 0x2, - StrikeOut = 0x4, - RightToLeft = 0x8 + Overline = 0x01, + Underline = 0x02, + StrikeOut = 0x04, + RightToLeft = 0x08, + SplitLigature = 0x10, }; Q_DECLARE_FLAGS(GlyphRunFlags, GlyphRunFlag) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 3e7c0ad4ab..d3f8cb7cde 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1015,15 +1015,7 @@ QList QTextLayout::glyphRuns(int from, int length) const QRawFont rawFont = glyphRun.rawFont(); QFontEngine *fontEngine = rawFont.d->fontEngine; - QTextItem::RenderFlags flags; - if (glyphRun.underline()) - flags |= QTextItem::Underline; - if (glyphRun.overline()) - flags |= QTextItem::Overline; - if (glyphRun.strikeOut()) - flags |= QTextItem::StrikeOut; - if (glyphRun.isRightToLeft()) - flags |= QTextItem::RightToLeft; + QGlyphRun::GlyphRunFlags flags = glyphRun.flags(); QPair key(fontEngine, int(flags)); // merge the glyph runs using the same font if (glyphRunHash.contains(key)) { @@ -2106,7 +2098,7 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q #if !defined(QT_NO_RAWFONT) static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout, - const QPointF &pos, const QTextItem::RenderFlags &flags, + const QPointF &pos, const QGlyphRun::GlyphRunFlags &flags, const QFixed &selectionX, const QFixed &selectionWidth) { QGlyphRun glyphRun; @@ -2137,7 +2129,17 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g QVarLengthArray glyphsArray; QVarLengthArray positionsArray; - fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + QTextItem::RenderFlags renderFlags; + if (flags.testFlag(QGlyphRun::Overline)) + renderFlags |= QTextItem::Overline; + if (flags.testFlag(QGlyphRun::Underline)) + renderFlags |= QTextItem::Underline; + if (flags.testFlag(QGlyphRun::StrikeOut)) + renderFlags |= QTextItem::StrikeOut; + if (flags.testFlag(QGlyphRun::RightToLeft)) + renderFlags |= QTextItem::RightToLeft; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), renderFlags, glyphsArray, positionsArray); Q_ASSERT(glyphsArray.size() == positionsArray.size()); @@ -2164,12 +2166,7 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g glyphRun.setGlyphIndexes(glyphs); glyphRun.setPositions(positions); - - glyphRun.setOverline(flags.testFlag(QTextItem::Overline)); - glyphRun.setUnderline(flags.testFlag(QTextItem::Underline)); - glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); - if (flags.testFlag(QTextItem::RightToLeft)) - glyphRun.setRightToLeft(true); + glyphRun.setFlags(flags); glyphRun.setRawFont(font); glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY, selectionWidth.toReal(), height)); @@ -2229,17 +2226,17 @@ QList QTextLine::glyphRuns(int from, int length) const QFont font = eng->font(si); - QTextItem::RenderFlags flags; + QGlyphRun::GlyphRunFlags flags; if (font.overline()) - flags |= QTextItem::Overline; + flags |= QGlyphRun::Overline; if (font.underline()) - flags |= QTextItem::Underline; + flags |= QGlyphRun::Underline; if (font.strikeOut()) - flags |= QTextItem::StrikeOut; + flags |= QGlyphRun::StrikeOut; bool rtl = false; if (si.analysis.bidiLevel % 2) { - flags |= QTextItem::RightToLeft; + flags |= QGlyphRun::RightToLeft; rtl = true; } @@ -2251,6 +2248,9 @@ QList QTextLine::glyphRuns(int from, int length) const int glyphsEnd = (relativeTo == eng->length(&si)) ? si.num_glyphs - 1 : logClusters[relativeTo]; + bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart; + bool endsInsideLigature = relativeTo < eng->length(&si) - 1 + && logClusters[relativeTo + 1] == glyphsEnd; int itemGlyphsStart = logClusters[iterator.itemStart - si.position]; int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position]; @@ -2294,8 +2294,13 @@ QList QTextLine::glyphRuns(int from, int length) const QGlyphLayout subLayout = glyphLayout.mid(start, end - start); multiFontEngine->ensureEngineAt(which); + + QGlyphRun::GlyphRunFlags subFlags = flags; + if (start == 0 && startsInsideLigature) + subFlags |= QGlyphRun::SplitLigature; + glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which), - subLayout, pos, flags, x, width)); + subLayout, pos, subFlags, x, width)); for (int i = 0; i < subLayout.numGlyphs; i++) { pos += QPointF(subLayout.advances_x[i].toReal(), subLayout.advances_y[i].toReal()); @@ -2307,11 +2312,18 @@ QList QTextLine::glyphRuns(int from, int length) const QGlyphLayout subLayout = glyphLayout.mid(start, end - start); multiFontEngine->ensureEngineAt(which); + + QGlyphRun::GlyphRunFlags subFlags = flags; + if ((start == 0 && startsInsideLigature) || endsInsideLigature) + subFlags |= QGlyphRun::SplitLigature; + QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which), - subLayout, pos, flags, x, width); + subLayout, pos, subFlags, x, width); if (!glyphRun.isEmpty()) glyphRuns.append(glyphRun); } else { + if (startsInsideLigature || endsInsideLigature) + flags |= QGlyphRun::SplitLigature; QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags, x, width); if (!glyphRun.isEmpty()) -- cgit v1.2.3