From d52fd497f60a3c4456994f4f10e9451d611c9ea4 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 12 Dec 2011 13:02:13 +0100 Subject: 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 --- src/gui/painting/qpaintengine_raster.cpp | 87 +++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 89a8f8a032..60ead45eab 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2878,11 +2878,47 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect, return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend; } +static QPair 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(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 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(©); } 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(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 positions; QVarLengthArray 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 positions; + QVarLengthArray glyphs; + + ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform::fromTranslate(p.x(), p.y()), + ti.flags, glyphs, positions); + QPair range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()), + ti.fontEngine, glyphs.data(), positions.data(), + glyphs.size()); + if (range.first >= range.second) + return; - QPaintEngineEx::drawTextItem(p, ti); + 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); + } } /*! -- cgit v1.2.3