Skip to content

Commit

Permalink
Small Text creation performance improvements.
Browse files Browse the repository at this point in the history
Change-Id: Ie92129887730d3738e14116cf22e1c30b836a415
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
  • Loading branch information
Martin Jones authored and Qt by Nokia committed Dec 20, 2011
1 parent 657f6d7 commit b26bda8
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 32 deletions.
78 changes: 51 additions & 27 deletions src/quick/items/qquicktext.cpp
Expand Up @@ -78,9 +78,10 @@ QQuickTextPrivate::QQuickTextPrivate()
format(QQuickText::AutoText), wrapMode(QQuickText::NoWrap), lineHeight(1),
lineHeightMode(QQuickText::ProportionalHeight), lineCount(1), maximumLineCount(INT_MAX),
maximumLineCountValid(false),
texture(0),
imageCache(0), texture(0),
imageCacheDirty(false), updateOnComponentComplete(true),
richText(false), styledText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false),
richText(false), styledText(false), singleline(false), cacheAllTextAsImage(true),
disableDistanceField(false), internalWidthUpdate(false),
requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
layoutTextElided(false), richTextAsImage(false), textureImageCacheDirty(false), textHasChanged(true),
naturalWidth(0), doc(0), elipsisLayout(0), textLine(0), nodeType(NodeIsNull)
Expand All @@ -91,6 +92,7 @@ QQuickTextPrivate::QQuickTextPrivate()

{
cacheAllTextAsImage = enableImageCache();
disableDistanceField = qmlDisableDistanceField();
}

void QQuickTextPrivate::init()
Expand Down Expand Up @@ -188,6 +190,7 @@ QQuickTextPrivate::~QQuickTextPrivate()
{
delete elipsisLayout;
delete textLine; textLine = 0;
delete imageCache;
}

qreal QQuickTextPrivate::getImplicitWidth() const
Expand Down Expand Up @@ -217,9 +220,11 @@ void QQuickTextPrivate::updateLayout()
delete elipsisLayout;
elipsisLayout = 0;
}
layout.clearLayout();
layout.setFont(font);
if (!styledText) {
if (text.isEmpty()) {
if (!layout.text().isEmpty())
layout.setText(text);
} else if (!styledText) {
QString tmp = text;
tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
singleline = !tmp.contains(QChar::LineSeparator);
Expand Down Expand Up @@ -281,8 +286,9 @@ void QQuickTextPrivate::updateSize()

QFontMetrics fm(font);
if (text.isEmpty()) {
q->setImplicitSize(0, fm.height());
paintedSize = QSize(0, fm.height());
qreal fontHeight = fm.height();
q->setImplicitSize(0, fontHeight);
paintedSize = QSize(0, fontHeight);
emit q->paintedSizeChanged();
q->update();
return;
Expand Down Expand Up @@ -315,7 +321,7 @@ void QQuickTextPrivate::updateSize()
QTextOption option;
option.setAlignment((Qt::Alignment)int(horizontalAlignment | vAlign));
option.setWrapMode(QTextOption::WrapMode(wrapMode));
if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
if (!cacheAllTextAsImage && !richTextAsImage && !disableDistanceField)
option.setUseDesignMetrics(true);
doc->setDefaultTextOption(option);
if (requireImplicitWidth && q->widthValid()) {
Expand Down Expand Up @@ -451,9 +457,9 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,

#if defined(Q_OS_MAC)
if (QThread::currentThread() != paintingThread) {
#endif
if (!line.lineNumber())
linesRects.clear();
#endif

if (!textLine)
textLine = new QQuickTextLine;
Expand All @@ -471,10 +477,11 @@ void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height,

emit q->lineLaidOut(textLine);

linesRects << QRectF(textLine->x(), textLine->y(), textLine->width(), textLine->height());
height += textLine->height();

#if defined(Q_OS_MAC)
linesRects << QRectF(textLine->x(), textLine->y(), textLine->width(), textLine->height());

} else {
if (line.lineNumber() < linesRects.count()) {
QRectF r = linesRects.at(line.lineNumber());
Expand Down Expand Up @@ -508,7 +515,7 @@ QRect QQuickTextPrivate::setupTextLayout()
QTextOption textOption = layout.textOption();
textOption.setAlignment(Qt::Alignment(q->effectiveHAlign()));
textOption.setWrapMode(QTextOption::WrapMode(wrapMode));
if (!cacheAllTextAsImage && !richTextAsImage && !qmlDisableDistanceField())
if (!cacheAllTextAsImage && !richTextAsImage && !disableDistanceField)
textOption.setUseDesignMetrics(true);
layout.setTextOption(textOption);

Expand Down Expand Up @@ -731,23 +738,33 @@ QPixmap QQuickTextPrivate::textDocumentImage(bool drawStyle)
return img;
}


void QQuickTextPrivate::markDirty()
{
Q_Q(QQuickText);
if (!invalidateImageCache() && q->isComponentComplete())
q->update();
}

/*!
Mark the image cache as dirty.
*/
void QQuickTextPrivate::invalidateImageCache()
bool QQuickTextPrivate::invalidateImageCache()
{
Q_Q(QQuickText);

if (richTextAsImage || cacheAllTextAsImage || (qmlDisableDistanceField() && style != QQuickText::Normal)) { // If actually using the image cache
if (richTextAsImage || cacheAllTextAsImage || (disableDistanceField && style != QQuickText::Normal)) { // If actually using the image cache
if (imageCacheDirty)
return;
return true;

imageCacheDirty = true;

if (q->isComponentComplete())
QCoreApplication::postEvent(q, new QEvent(QEvent::User));
} else if (q->isComponentComplete())
q->update();
return true;
}

return false;
}

/*!
Expand All @@ -762,7 +779,8 @@ void QQuickTextPrivate::checkImageCache()

if (text.isEmpty()) {

imageCache = QPixmap();
delete imageCache;
imageCache = 0;

} else {

Expand All @@ -779,18 +797,19 @@ void QQuickTextPrivate::checkImageCache()
styledImage = textLayoutImage(true); //### should use styleColor
}

delete imageCache;
switch (style) {
case QQuickText::Outline:
imageCache = drawOutline(textImage, styledImage);
imageCache = new QPixmap(drawOutline(textImage, styledImage));
break;
case QQuickText::Sunken:
imageCache = drawOutline(textImage, styledImage, -1);
imageCache = new QPixmap(drawOutline(textImage, styledImage, -1));
break;
case QQuickText::Raised:
imageCache = drawOutline(textImage, styledImage, 1);
imageCache = new QPixmap(drawOutline(textImage, styledImage, 1));
break;
default:
imageCache = textImage;
imageCache = new QPixmap(textImage);
break;
}

Expand Down Expand Up @@ -1183,7 +1202,7 @@ void QQuickText::setColor(const QColor &color)
return;

d->color = color;
d->invalidateImageCache();
d->markDirty();
emit colorChanged(d->color);
}
/*!
Expand Down Expand Up @@ -1226,7 +1245,7 @@ void QQuickText::setStyle(QQuickText::TextStyle style)
if (isComponentComplete() && (d->style == Normal || style == Normal))
update();
d->style = style;
d->invalidateImageCache();
d->markDirty();
emit styleChanged(d->style);
}

Expand Down Expand Up @@ -1258,7 +1277,7 @@ void QQuickText::setStyleColor(const QColor &color)
return;

d->styleColor = color;
d->invalidateImageCache();
d->markDirty();
emit styleColorChanged(d->styleColor);
}

Expand Down Expand Up @@ -1653,6 +1672,11 @@ QRectF QQuickText::boundingRect() const
void QQuickText::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickText);
if (d->text.isEmpty()) {
QQuickItem::geometryChanged(newGeometry, oldGeometry);
return;
}

bool widthChanged = newGeometry.width() != oldGeometry.width();
bool heightChanged = newGeometry.height() != oldGeometry.height();
bool leftAligned = effectiveHAlign() == QQuickText::AlignLeft;
Expand Down Expand Up @@ -1714,11 +1738,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
#endif

// XXX todo - some styled text can be done by the QQuickTextNode
if (d->richTextAsImage || d->cacheAllTextAsImage || (qmlDisableDistanceField() && d->style != Normal)) {
if (d->richTextAsImage || d->cacheAllTextAsImage || (d->disableDistanceField && d->style != Normal)) {
bool wasDirty = d->textureImageCacheDirty;
d->textureImageCacheDirty = false;

if (d->imageCache.isNull()) {
if (!d->imageCache || d->imageCache->isNull()) {
delete oldNode;
return 0;
}
Expand All @@ -1736,12 +1760,12 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
}

if (wasDirty) {
qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->imageCache.toImage());
qobject_cast<QSGPlainTexture *>(d->texture)->setImage(d->imageCache->toImage());
node->setTexture(0);
node->setTexture(d->texture);
}

node->setTargetRect(QRectF(bounds.x(), bounds.y(), d->imageCache.width(), d->imageCache.height()));
node->setTargetRect(QRectF(bounds.x(), bounds.y(), d->imageCache->width(), d->imageCache->height()));
node->setSourceRect(QRectF(0, 0, 1, 1));
node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
node->setVerticalWrapMode(QSGTexture::ClampToEdge);
Expand Down
8 changes: 5 additions & 3 deletions src/quick/items/qquicktext_p_p.h
Expand Up @@ -103,9 +103,10 @@ class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate

static QString elideChar;

void invalidateImageCache();
void markDirty();
bool invalidateImageCache();
void checkImageCache();
QPixmap imageCache;
QPixmap *imageCache;
QSGTexture *texture;

bool imageCacheDirty:1;
Expand All @@ -114,6 +115,7 @@ class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
bool styledText:1;
bool singleline:1;
bool cacheAllTextAsImage:1;
bool disableDistanceField:1;
bool internalWidthUpdate:1;
bool requireImplicitWidth:1;
bool truncated:1;
Expand Down Expand Up @@ -141,7 +143,6 @@ class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
QString anchorAt(const QPointF &pos);
QTextLayout layout;
QTextLayout *elipsisLayout;
QList<QRectF> linesRects;
QQuickTextLine *textLine;

static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource);
Expand All @@ -159,6 +160,7 @@ class Q_AUTOTEST_EXPORT QQuickTextPrivate : public QQuickImplicitSizeItemPrivate
NodeType nodeType;

#if defined(Q_OS_MAC)
QList<QRectF> linesRects;
QThread *layoutThread;
QThread *paintingThread;
#endif
Expand Down
6 changes: 4 additions & 2 deletions tests/auto/qtquick2/qquicktext/tst_qquicktext.cpp
Expand Up @@ -1443,10 +1443,12 @@ void tst_qquicktext::lineLaidOut()
QTextDocument *doc = textPrivate->textDocument();
QVERIFY(doc == 0);

#if defined(Q_OS_MAC)
QVERIFY(myText->lineCount() == textPrivate->linesRects.count());
#endif

for (int i = 0; i < textPrivate->linesRects.count(); ++i) {
QRectF r = textPrivate->linesRects.at(i);
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
QRectF r = textPrivate->layout.lineAt(i).rect();
QVERIFY(r.width() == i * 15);
if (i >= 30)
QVERIFY(r.x() == r.width() + 30);
Expand Down

0 comments on commit b26bda8

Please sign in to comment.