From 399208c54b18bf7dd671439107fbb9910218a51c Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 30 Jun 2011 12:45:44 +0200 Subject: Move glyph run merging logic to QTextLayout level So that we can merge glyph runs from different QTextLines. Change-Id: Id8e0cc1aa21a482a995773fd55599c0011245e82 Reviewed-on: http://codereview.qt.nokia.com/950 Reviewed-by: Qt Sanity Bot Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qrawfont.h | 1 + src/gui/text/qtextlayout.cpp | 210 +++++++++++++++++++++---------------------- 2 files changed, 101 insertions(+), 110 deletions(-) (limited to 'src/gui') diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index d517c9ad7a..e94bd99b8c 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -135,6 +135,7 @@ public: private: friend class QRawFontPrivate; + friend class QTextLayout; void detach(); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f9bfcbfce7..ae978b019a 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1004,15 +1004,46 @@ QList QTextLayout::glyphRuns(int from, int length) const if (length < 0) length = text().length(); - QList glyphs; + QHash, QGlyphRun> glyphRunHash; for (int i=0; ilines.size(); ++i) { if (d->lines[i].from > from + length) break; - else if (d->lines[i].from + d->lines[i].length >= from) - glyphs += QTextLine(i, d).glyphRuns(from, length); + else if (d->lines[i].from + d->lines[i].length >= from) { + QList glyphRuns = QTextLine(i, d).glyphRuns(from, length); + + for (int j = 0; j < glyphRuns.size(); j++) { + const QGlyphRun &glyphRun = glyphRuns.at(j); + 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; + QPair key(fontEngine, int(flags)); + // merge the glyph runs using the same font + if (glyphRunHash.contains(key)) { + QGlyphRun &oldGlyphRun = glyphRunHash[key]; + + QVector indexes = oldGlyphRun.glyphIndexes(); + QVector positions = oldGlyphRun.positions(); + + indexes += glyphRun.glyphIndexes(); + positions += glyphRun.positions(); + + oldGlyphRun.setGlyphIndexes(indexes); + oldGlyphRun.setPositions(positions); + } else { + glyphRunHash[key] = glyphRun; + } + } + } } - return glyphs; + return glyphRunHash.values(); } #endif // QT_NO_RAWFONT @@ -2077,19 +2108,65 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } -namespace { - struct GlyphInfo - { - GlyphInfo(const QGlyphLayout &layout, const QPointF &position, - const QTextItemInt::RenderFlags &renderFlags) - : glyphLayout(layout), itemPosition(position), flags(renderFlags) - { - } +static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout, + const QPointF &pos, const QTextItem::RenderFlags &flags) +{ + QGlyphRun glyphRun; - QGlyphLayout glyphLayout; - QPointF itemPosition; - QTextItem::RenderFlags flags; - }; + // Make a font for this particular engine + QRawFont font; + QRawFontPrivate *fontD = QRawFontPrivate::get(font); + fontD->fontEngine = fontEngine; + fontD->fontEngine->ref.ref(); + +#if defined(Q_WS_WIN) + if (fontEngine->supportsSubPixelPositions()) + fontD->hintingPreference = QFont::PreferVerticalHinting; + else + fontD->hintingPreference = QFont::PreferFullHinting; +#elif defined(Q_WS_MAC) + fontD->hintingPreference = QFont::PreferNoHinting; +#elif !defined(QT_NO_FREETYPE) + if (fontEngine->type() == QFontEngine::Freetype) { + QFontEngineFT *freeTypeEngine = static_cast(fontEngine); + switch (freeTypeEngine->defaultHintStyle()) { + case QFontEngineFT::HintNone: + fontD->hintingPreference = QFont::PreferNoHinting; + break; + case QFontEngineFT::HintLight: + fontD->hintingPreference = QFont::PreferVerticalHinting; + break; + case QFontEngineFT::HintMedium: + case QFontEngineFT::HintFull: + fontD->hintingPreference = QFont::PreferFullHinting; + break; + }; + } +#endif + + QVarLengthArray glyphsArray; + QVarLengthArray positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector glyphs; + QVector positions; + for (int i=0; i QTextLine::glyphRuns(int from, int length) const if (length < 0) length = textLength(); - QHash glyphLayoutHash; - QTextLineItemIterator iterator(eng, i); qreal y = line.y.toReal() + line.base().toReal(); + QList glyphRuns; while (!iterator.atEnd()) { QScriptItem &si = iterator.next(); if (si.analysis.flags >= QScriptAnalysis::TabOrObject) @@ -2193,8 +2269,8 @@ QList QTextLine::glyphRuns(int from, int length) const continue; QGlyphLayout subLayout = glyphLayout.mid(start, end - start); - glyphLayoutHash.insertMulti(multiFontEngine->engine(which), - GlyphInfo(subLayout, pos, flags)); + glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which), + subLayout, pos, flags)); for (int i = 0; i < subLayout.numGlyphs; i++) { pos += QPointF(subLayout.advances_x[i].toReal(), subLayout.advances_y[i].toReal()); @@ -2205,101 +2281,15 @@ QList QTextLine::glyphRuns(int from, int length) const } QGlyphLayout subLayout = glyphLayout.mid(start, end - start); - glyphLayoutHash.insertMulti(multiFontEngine->engine(which), - GlyphInfo(subLayout, pos, flags)); - + glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which), + subLayout, pos, flags)); } else { - glyphLayoutHash.insertMulti(mainFontEngine, - GlyphInfo(glyphLayout, pos, flags)); - } - } - } - - QHash, QGlyphRun> glyphsHash; - - QList keys = glyphLayoutHash.uniqueKeys(); - for (int i=0; ifontEngine = fontEngine; - fontD->fontEngine->ref.ref(); - -#if defined(Q_WS_WIN) - if (fontEngine->supportsSubPixelPositions()) - fontD->hintingPreference = QFont::PreferVerticalHinting; - else - fontD->hintingPreference = QFont::PreferFullHinting; -#elif defined(Q_WS_MAC) - fontD->hintingPreference = QFont::PreferNoHinting; -#elif !defined(QT_NO_FREETYPE) - if (fontEngine->type() == QFontEngine::Freetype) { - QFontEngineFT *freeTypeEngine = static_cast(fontEngine); - switch (freeTypeEngine->defaultHintStyle()) { - case QFontEngineFT::HintNone: - fontD->hintingPreference = QFont::PreferNoHinting; - break; - case QFontEngineFT::HintLight: - fontD->hintingPreference = QFont::PreferVerticalHinting; - break; - case QFontEngineFT::HintMedium: - case QFontEngineFT::HintFull: - fontD->hintingPreference = QFont::PreferFullHinting; - break; - }; - } -#endif - - QList glyphLayouts = glyphLayoutHash.values(fontEngine); - for (int j=0; j glyphsArray; - QVarLengthArray positionsArray; - - fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, - positionsArray); - Q_ASSERT(glyphsArray.size() == positionsArray.size()); - - QVector glyphs; - QVector positions; - for (int i=0; i key(fontEngine, int(flags)); - if (!glyphsHash.contains(key)) { - glyphsHash.insert(key, glyphIndexes); - } else { - QGlyphRun &glyphRun = glyphsHash[key]; - - QVector indexes = glyphRun.glyphIndexes(); - QVector positions = glyphRun.positions(); - - indexes += glyphIndexes.glyphIndexes(); - positions += glyphIndexes.positions(); - - glyphRun.setGlyphIndexes(indexes); - glyphRun.setPositions(positions); + glyphRuns.append(glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags)); } } } - return glyphsHash.values(); + return glyphRuns; } #endif // QT_NO_RAWFONT -- cgit v1.2.3