Improved performance of large text when parts are outside view.

Avoid generating paths for the parts of the text that are outside
the viewport in the raster paint engine.

Task-number: QTBUG-22687
Change-Id: I06159bc4c1aa82a07606f4b2f0336cb25dfd56d2
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
bb10
Kim Motoyoshi Kalland 2011-12-12 13:02:13 +01:00 committed by Qt by Nokia
parent 0553ab9127
commit d52fd497f6
1 changed files with 82 additions and 7 deletions

View File

@ -2878,11 +2878,47 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
}
static QPair<int, int> visibleGlyphRange(const QRectF &clip, QFontEngine *fontEngine,
glyph_t *glyphs, QFixedPoint *positions, int numGlyphs)
{
QFixed clipLeft = QFixed::fromReal(clip.left());
QFixed clipRight = QFixed::fromReal(clip.right());
QFixed clipTop = QFixed::fromReal(clip.top());
QFixed clipBottom = QFixed::fromReal(clip.bottom());
int first = 0;
while (first < numGlyphs) {
glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[first]);
QFixed left = metrics.x + positions[first].x;
QFixed top = metrics.y + positions[first].y;
QFixed right = left + metrics.width;
QFixed bottom = top + metrics.height;
if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop)
break;
++first;
}
int last = numGlyphs - 1;
while (last > first) {
glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[last]);
QFixed left = metrics.x + positions[last].x;
QFixed top = metrics.y + positions[last].y;
QFixed right = left + metrics.width;
QFixed bottom = top + metrics.height;
if (left < clipRight && right > clipLeft && top < clipBottom && bottom > clipTop)
break;
--last;
}
return QPair<int, int>(first, last + 1);
}
/*!
\reimp
*/
void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
{
if (textItem->numGlyphs == 0)
return;
ensurePen();
ensureRasterState();
@ -2890,6 +2926,20 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) {
drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions,
fontEngine);
} else if (state()->matrix.type() < QTransform::TxProject) {
bool invertible;
QTransform invMat = state()->matrix.inverted(&invertible);
if (!invertible)
return;
QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
textItem->fontEngine(), textItem->glyphs,
textItem->glyphPositions, textItem->numGlyphs);
QStaticTextItem copy = *textItem;
copy.glyphs += range.first;
copy.glyphPositions += range.first;
copy.numGlyphs = range.second - range.first;
QPaintEngineEx::drawStaticTextItem(&copy);
} else {
QPaintEngineEx::drawStaticTextItem(textItem);
}
@ -2901,7 +2951,6 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
QRasterPaintEngineState *s = state();
#ifdef QT_DEBUG_DRAW
Q_D(QRasterPaintEngine);
@ -2910,25 +2959,51 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
d->glyphCacheType);
#endif
if (ti.glyphs.numGlyphs == 0)
return;
ensurePen();
ensureRasterState();
QRasterPaintEngineState *s = state();
QTransform matrix = s->matrix;
if (!supportsTransformations(ti.fontEngine)) {
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
QTransform matrix = s->matrix;
matrix.translate(p.x(), p.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine);
return;
} else if (matrix.type() < QTransform::TxProject) {
bool invertible;
QTransform invMat = matrix.inverted(&invertible);
if (!invertible)
return;
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform::fromTranslate(p.x(), p.y()),
ti.flags, glyphs, positions);
QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
ti.fontEngine, glyphs.data(), positions.data(),
glyphs.size());
if (range.first >= range.second)
return;
QStaticTextItem staticTextItem;
staticTextItem.color = s->pen.color();
staticTextItem.font = s->font;
staticTextItem.setFontEngine(ti.fontEngine);
staticTextItem.numGlyphs = range.second - range.first;
staticTextItem.glyphs = glyphs.data() + range.first;
staticTextItem.glyphPositions = positions.data() + range.first;
QPaintEngineEx::drawStaticTextItem(&staticTextItem);
} else {
QPaintEngineEx::drawTextItem(p, ti);
}
QPaintEngineEx::drawTextItem(p, ti);
}
/*!