1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include <QApplication>
46 #include <QPainterPath>
48 #include <QTextLayout>
49 #include <QVBoxLayout>
52 #include <QStaticText>
55 const int count = 600;
57 const int spacing = 36;
58 QSizeF size(1000, 800);
59 const qreal lineWidth = 1000;
60 QString strings[lines];
61 QGLWidget *testWidget = 0;
63 void paint_QTextLayout(QPainter &p, bool useCache)
65 static bool first = true;
66 static QTextLayout *textLayout[lines];
68 for (int i = 0; i < lines; ++i) {
69 textLayout[i] = new QTextLayout(strings[i]);
70 int leading = p.fontMetrics().leading();
73 textLayout[i]->setCacheEnabled(useCache);
74 textLayout[i]->beginLayout();
76 QTextLine line = textLayout[i]->createLine();
80 line.setLineWidth(lineWidth);
82 line.setPosition(QPointF(0, height));
83 height += line.height();
84 widthUsed = qMax(widthUsed, line.naturalTextWidth());
86 textLayout[i]->endLayout();
90 for (int i = 0; i < count; ++i) {
91 for (int j = 0; j < lines; ++j) {
92 textLayout[j]->draw(&p, QPoint(0, j*spacing));
97 void paint_QTextLayout_noCache(QPainter &p)
99 paint_QTextLayout(p, false);
102 void paint_QTextLayout_cache(QPainter &p)
104 paint_QTextLayout(p, true);
107 void paint_QStaticText(QPainter &p, bool useOptimizations)
109 static QStaticText *staticText[lines];
110 static bool first = true;
112 for (int i = 0; i < lines; ++i) {
113 staticText[i] = new QStaticText(strings[i]);
114 if (useOptimizations)
115 staticText[i]->setPerformanceHint(QStaticText::AggressiveCaching);
117 staticText[i]->setPerformanceHint(QStaticText::ModerateCaching);
121 for (int i = 0; i < count; ++i) {
122 for (int j = 0; j < lines; ++j) {
123 p.drawStaticText(QPointF(0, 30 + j*spacing), *staticText[j]);
128 void paint_QStaticText_noOptimizations(QPainter &p)
130 paint_QStaticText(p, false);
133 void paint_QStaticText_optimizations(QPainter &p)
135 paint_QStaticText(p, true);
138 void paint_QPixmapCachedText(QPainter &p)
140 static bool first = true;
141 static QPixmap cacheText[lines];
143 for (int i = 0; i < lines; ++i) {
145 trueSize = p.boundingRect(QRectF(QPointF(0,0), size), 0, strings[i]);
146 cacheText[i] = QPixmap(trueSize.size().toSize());
147 cacheText[i].fill(Qt::transparent);
148 QPainter paint(&cacheText[i]);
149 paint.setPen(Qt::black);
150 paint.drawText(QRectF(QPointF(0,0), trueSize.size().toSize()), strings[i]);
154 for (int i = 0; i < count; i++) {
155 for (int j = 0; j < lines; ++j) {
156 p.drawPixmap(0,j*spacing,cacheText[j]);
161 void paint_RoundedRect(QPainter &p)
163 static bool first = true;
166 QGLFormat format = testWidget->format();
167 if (!format.sampleBuffers())
168 qWarning() << "Cannot paint antialiased rounded rect without sampleBuffers";
172 p.setRenderHint(QPainter::Antialiasing, true);
175 for (int i = 0; i < count; i++) {
176 for (int j = 0; j < lines; ++j) {
177 QSize size((j+1)*50, spacing-1);
178 p.drawRoundedRect(QRectF(QPointF(0,j*spacing), size), 8, 8);
183 void paint_QPixmapCachedRoundedRect(QPainter &p)
185 static bool first = true;
186 static QPixmap cacheRect;
189 const int radius = 8;
190 cacheRect = QPixmap(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2);
191 cacheRect.fill(Qt::transparent);
192 QPainter paint(&cacheRect);
193 paint.setRenderHint(QPainter::Antialiasing);
194 paint.setPen(Qt::black);
195 paint.setBrush(Qt::red);
197 paint.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, cacheRect.width()-(pw+1), cacheRect.height()-(pw+1)), radius, radius);
199 paint.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, cacheRect.width()-pw, cacheRect.height()-pw), radius, radius);
203 for (int i = 0; i < count; i++) {
204 for (int j = 0; j < lines; ++j) {
205 QSize size((j+1)*50, spacing-1);
207 p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
211 int xOffset = (cacheRect.width()-1)/2;
212 int yOffset = (cacheRect.height()-1)/2;
214 QMargins margins(xOffset, yOffset, xOffset, yOffset);
215 QTileRules rules(Qt::StretchTile, Qt::StretchTile);
216 //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
217 qDrawBorderPixmap(&p, QRect(-pw/2, j*spacing-pw/2, size.width()+pw, size.height()+pw), margins, cacheRect, cacheRect.rect(), margins, rules);
222 void paint_pathCacheRoundedRect(QPainter &p)
224 static bool first = true;
225 static QPainterPath path[lines];
227 for (int j = 0; j < lines; ++j) {
228 path[j].addRoundedRect(QRectF(0,0,(j+1)*50, spacing-1), 8, 8);
232 p.setRenderHint(QPainter::Antialiasing, true);
235 for (int i = 0; i < count; i++) {
236 for (int j = 0; j < lines; ++j) {
237 p.translate(0,j*spacing);
239 p.translate(0,-j*spacing);
244 void paint_QPixmap63x63_opaque(QPainter &p)
246 static bool first = true;
249 pm.load("data/63x63_opaque.png");
252 for (int i = 0; i < count; i++) {
253 for (int j = 0; j < lines; ++j) {
254 p.drawPixmap((i%10) * 64,j*spacing, pm);
259 void paint_QPixmap64x64_opaque(QPainter &p)
261 static bool first = true;
264 pm.load("data/64x64_opaque.png");
267 for (int i = 0; i < count; i++) {
268 for (int j = 0; j < lines; ++j) {
269 p.drawPixmap((i%10) * 64,j*spacing, pm);
274 void paint_QPixmap63x63(QPainter &p)
276 static bool first = true;
279 pm.load("data/63x63.png");
282 for (int i = 0; i < count; i++) {
283 for (int j = 0; j < lines; ++j) {
284 p.drawPixmap((i%10) * 64,j*spacing, pm);
289 void paint_QPixmap64x64(QPainter &p)
291 static bool first = true;
294 pm.load("data/64x64.png");
297 for (int i = 0; i < count; i++) {
298 for (int j = 0; j < lines; ++j) {
299 p.drawPixmap((i%10) * 64,j*spacing, pm);
303 typedef void(*PaintFunc)(QPainter &);
309 { "QTextLayoutNoCache", &paint_QTextLayout_noCache },
310 { "QTextLayoutWithCache", &paint_QTextLayout_cache },
311 { "QStaticTextNoBackendOptimizations", &paint_QStaticText_noOptimizations },
312 { "QStaticTextWithBackendOptimizations", &paint_QStaticText_optimizations },
313 { "CachedText", &paint_QPixmapCachedText },
314 { "RoundedRect", &paint_RoundedRect },
315 { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect },
316 { "PathCacheRoundedRect", &paint_pathCacheRoundedRect },
317 { "QPixmap63x63_opaque", &paint_QPixmap63x63_opaque },
318 { "QPixmap64x64_opaque", &paint_QPixmap64x64_opaque },
319 { "QPixmap63x63", &paint_QPixmap63x63 },
320 { "QPixmap64x64", &paint_QPixmap64x64 },
324 PaintFunc testFunc = 0;
326 class MyGLWidget : public QGLWidget
329 MyGLWidget(const QGLFormat &format) : QGLWidget(format), frames(0) {
330 const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234";
331 int len = strlen(chars);
332 for (int i = 0; i < lines; ++i) {
333 for (int j = 0; j < 60; j++) {
334 strings[i] += QChar(chars[rand() % len]);
339 void paintEvent(QPaintEvent *) {
341 static bool firstRun = true;
346 int elapsed = timer.elapsed();
347 qDebug() << "frame elapsed:" << elapsed - last;
351 p.fillRect(rect(), Qt::white);
356 qDebug() << "draw time" << drawTimer.elapsed();
367 int main(int argc, char *argv[])
369 QApplication app(argc, argv);
371 bool sampleBuffers = false;
373 for (int i = 1; i < argc; ++i) {
374 QString arg = argv[i];
375 if (arg == "-test") {
378 while (funcs[j].name) {
379 if (arg == funcs[j].name) {
380 testFunc = funcs[j].func;
381 qDebug() << "Running test" << arg;
386 } else if (arg == "-iterations") {
388 iterations = arg.toInt();
389 } else if (arg == "-sampleBuffers") {
390 sampleBuffers = true;
395 qDebug() << "Usage: textspeed -test <test> [-sampleBuffers] [-iterations n]";
396 qDebug() << "where <test> can be:";
398 while (funcs[j].name) {
399 qDebug() << " " << funcs[j].name;
406 QGLFormat format = QGLFormat::defaultFormat();
407 format.setSampleBuffers(sampleBuffers);
408 testWidget = new MyGLWidget(format);
409 testWidget->setAutoFillBackground(false);
410 QVBoxLayout *layout = new QVBoxLayout(&w);
412 layout->addWidget(testWidget);