diff options
author | Jiang Jiang <jiang.jiang@nokia.com> | 2011-06-30 12:45:44 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-06-30 13:16:41 +0200 |
commit | 399208c54b18bf7dd671439107fbb9910218a51c (patch) | |
tree | 63f62d9fbe7dbe321aa27d7836331cc6f0fc1e48 /src/gui | |
parent | 13b83d896de8b00d6a373c97917ce52553a7e451 (diff) |
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 <qt_sanity_bot@ovi.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/text/qrawfont.h | 1 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 210 |
2 files changed, 101 insertions, 110 deletions
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<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const if (length < 0) length = text().length(); - QList<QGlyphRun> glyphs; + QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash; for (int i=0; i<d->lines.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<QGlyphRun> 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<QFontEngine *, int> key(fontEngine, int(flags)); + // merge the glyph runs using the same font + if (glyphRunHash.contains(key)) { + QGlyphRun &oldGlyphRun = glyphRunHash[key]; + + QVector<quint32> indexes = oldGlyphRun.glyphIndexes(); + QVector<QPointF> 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<QFontEngineFT *>(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<glyph_t> glyphsArray; + QVarLengthArray<QFixedPoint> positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector<quint32> glyphs; + QVector<QPointF> positions; + for (int i=0; i<glyphsArray.size(); ++i) { + glyphs.append(glyphsArray.at(i) & 0xffffff); + positions.append(positionsArray.at(i).toPointF() + pos); + } + + glyphRun.setGlyphIndexes(glyphs); + glyphRun.setPositions(positions); + + glyphRun.setOverline(flags.testFlag(QTextItem::Overline)); + glyphRun.setUnderline(flags.testFlag(QTextItem::Underline)); + glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); + glyphRun.setRawFont(font); + + return glyphRun; } /*! @@ -2119,10 +2196,9 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const if (length < 0) length = textLength(); - QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; - QTextLineItemIterator iterator(eng, i); qreal y = line.y.toReal() + line.base().toReal(); + QList<QGlyphRun> glyphRuns; while (!iterator.atEnd()) { QScriptItem &si = iterator.next(); if (si.analysis.flags >= QScriptAnalysis::TabOrObject) @@ -2193,8 +2269,8 @@ QList<QGlyphRun> 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<QGlyphRun> 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<QPair<QFontEngine *, int>, QGlyphRun> glyphsHash; - - QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys(); - for (int i=0; i<keys.size(); ++i) { - QFontEngine *fontEngine = keys.at(i); - - // 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<QFontEngineFT *>(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<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine); - for (int j=0; j<glyphLayouts.size(); ++j) { - const QPointF &pos = glyphLayouts.at(j).itemPosition; - const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout; - const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags; - - QVarLengthArray<glyph_t> glyphsArray; - QVarLengthArray<QFixedPoint> positionsArray; - - fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, - positionsArray); - Q_ASSERT(glyphsArray.size() == positionsArray.size()); - - QVector<quint32> glyphs; - QVector<QPointF> positions; - for (int i=0; i<glyphsArray.size(); ++i) { - glyphs.append(glyphsArray.at(i) & 0xffffff); - positions.append(positionsArray.at(i).toPointF() + pos); - } - - QGlyphRun glyphIndexes; - glyphIndexes.setGlyphIndexes(glyphs); - glyphIndexes.setPositions(positions); - - glyphIndexes.setOverline(flags.testFlag(QTextItem::Overline)); - glyphIndexes.setUnderline(flags.testFlag(QTextItem::Underline)); - glyphIndexes.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); - glyphIndexes.setRawFont(font); - - QPair<QFontEngine *, int> key(fontEngine, int(flags)); - if (!glyphsHash.contains(key)) { - glyphsHash.insert(key, glyphIndexes); - } else { - QGlyphRun &glyphRun = glyphsHash[key]; - - QVector<quint32> indexes = glyphRun.glyphIndexes(); - QVector<QPointF> 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 |