OSDN Git Service

drop support for static text [ci reset]
[kde/Katie.git] / tests / benchmarks / gui / painting / qtbench / benchmarktests.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Copyright (C) 2016 Ivailo Monev
5 **
6 ** This file is part of the FOO module of the Katie Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 **
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser
12 ** General Public License version 2.1 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.LGPL included in the
14 ** packaging of this file.  Please review the following information to
15 ** ensure the GNU Lesser General Public License version 2.1 requirements
16 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** $QT_END_LICENSE$
19 **
20 ****************************************************************************/
21
22 #ifndef BENCHMARKTESTS_H
23 #define BENCHMARKTESTS_H
24
25 #include <QApplication>
26 #include <QTextDocument>
27 #include <QDesktopWidget>
28 #include <QTextLayout>
29 #include <QFontMetrics>
30 #include <QDebug>
31
32 class Benchmark
33 {
34 public:
35     virtual ~Benchmark() {}
36
37     Benchmark(const QSize &size)
38             : m_size(size)
39     {
40         for (int i=0; i<16; ++i) {
41             m_colors[i] = QColor::fromRgbF((rand() % 4) / 3.0,
42                                            (rand() % 4) / 3.0,
43                                            (rand() % 4) / 3.0,
44                                            1);
45         }
46     }
47
48     virtual void draw(QPainter *p, const QRect &rect, int iteration) = 0;
49     virtual QString name() const = 0;
50
51     inline const QSize &size() const
52     {
53         return m_size;
54     }
55     virtual void begin(QPainter *, int iterations = 1) { Q_UNUSED(iterations); }
56     virtual void end(QPainter *) { }
57
58     inline const QColor &randomColor(int i) { return m_colors[i % 16]; }
59
60 protected:
61     QColor m_colors[16];
62     QSize m_size;
63 };
64
65 class PaintingRectAdjuster
66 {
67 public:
68     PaintingRectAdjuster()
69             : m_benchmark(0),
70             m_bounds(),
71             m_screen_filled(false)
72     {
73     }
74
75     const QRect &newPaintingRect() {
76         m_rect.translate(m_rect.width(), 0);
77
78         if (m_rect.right() > m_bounds.width()) {
79             m_rect.moveLeft(m_bounds.left());
80             m_rect.translate(0,m_rect.height());
81             if (m_rect.bottom() > m_bounds.height()) {
82                 m_screen_filled = true;
83                 m_rect.moveTo(m_bounds.topLeft());
84             }
85         }
86         return m_rect;
87     }
88
89     inline bool isScreenFilled() const
90     { return m_screen_filled; }
91
92     void reset(const QRect &bounds)
93     {
94         m_bounds = bounds;
95         m_rect.moveTo(m_bounds.topLeft());
96         m_rect = QRect(m_bounds.topLeft(),m_benchmark->size());
97         m_rect.translate(-m_rect.width(),0);
98         m_screen_filled = false;
99     }
100
101     inline void setNewBenchmark( Benchmark *benchmark )
102     {
103         m_benchmark = benchmark;
104     }
105
106 protected:
107     Benchmark *m_benchmark;
108     QRect m_rect;
109     QRect m_bounds;
110     bool m_screen_filled;
111 };
112
113 class FillRectBenchmark : public Benchmark
114 {
115 public:
116     FillRectBenchmark(int size)
117         : Benchmark(QSize(size, size))
118     {
119     }
120
121     virtual void draw(QPainter *p, const QRect &rect, int iterationCount) {
122         p->fillRect(rect, randomColor(iterationCount));
123     }
124
125     virtual QString name() const {
126         return QString::fromLatin1("fillRect(%1)").arg(m_size.width());
127    }
128 };
129
130 class ImageFillRectBenchmark : public Benchmark
131 {
132 public:
133     ImageFillRectBenchmark(int size)
134         : Benchmark(QSize(size, size))
135     {
136         int s = rand() % 24 + 8;
137         m_content = QImage(s, s, QImage::Format_ARGB32_Premultiplied);
138         QPainter p(&m_content);
139         p.fillRect(0, 0, s, s, Qt::white);
140         p.fillRect(s/2, 0, s/2, s/2, Qt::gray);
141         p.fillRect(0, s/2, s/2, s/2, Qt::gray);
142         p.end();
143
144         m_brush = QBrush(m_content);
145     }
146
147     virtual void draw(QPainter *p, const QRect &rect, int) {
148         p->fillRect(rect, m_brush);
149     }
150
151     virtual QString name() const {
152         return QString::fromLatin1("fillRect with image(%1)").arg(m_size.width());
153    }
154
155 private:
156     QImage m_content;
157     QBrush m_brush;
158 };
159
160
161 class DrawRectBenchmark : public Benchmark
162 {
163 public:
164     DrawRectBenchmark(int size)
165         : Benchmark(QSize(size, size))
166     {
167     }
168
169     virtual void begin(QPainter *p, int) {
170         p->setPen(Qt::NoPen);
171         p->setBrush(randomColor(m_size.width()));
172     }
173
174
175     virtual void draw(QPainter *p, const QRect &rect, int) {
176         p->drawRect(rect);
177     }
178
179     virtual QString name() const {
180         return QString::fromLatin1("drawRect(%1)").arg(m_size.width());
181    }
182 };
183
184
185 class DrawRectWithBrushChangeBenchmark : public Benchmark
186 {
187 public:
188     DrawRectWithBrushChangeBenchmark(int size)
189         : Benchmark(QSize(size, size))
190     {
191     }
192
193     virtual void begin(QPainter *p, int) {
194         p->setPen(Qt::NoPen);
195     }
196
197
198     virtual void draw(QPainter *p, const QRect &rect, int i) {
199         p->setBrush(randomColor(i));
200         p->drawRect(rect);
201     }
202
203     virtual QString name() const {
204         return QString::fromLatin1("drawRect with brushchange(%1)").arg(m_size.width());
205    }
206 };
207
208 class RoundRectBenchmark : public Benchmark
209 {
210 public:
211     RoundRectBenchmark(int size)
212         : Benchmark(QSize(size, size))
213     {
214         m_roundness = size / 4.;
215     }
216
217     virtual void begin(QPainter *p, int) {
218         p->setPen(Qt::NoPen);
219         p->setBrush(Qt::red);
220     }
221
222     virtual void draw(QPainter *p, const QRect &rect, int) {
223         p->drawRoundedRect(rect, m_roundness, m_roundness);
224     }
225
226     virtual QString name() const {
227         return QString::fromLatin1("drawRoundedRect(%1)").arg(m_size.width());
228     }
229
230     qreal m_roundness;
231 };
232
233
234 class ArcsBenchmark : public Benchmark
235 {
236 public:
237     enum Type {
238         Stroked         = 0x0001,
239         Filled          = 0x0002,
240
241         ArcShape        = 0x0010,
242         ChordShape      = 0x0020,
243         PieShape        = 0x0040,
244         CircleShape     = 0x0080,
245         Shapes          = 0x00f0
246
247     };
248
249     ArcsBenchmark(int size, uint type)
250         : Benchmark(QSize(size, size)),
251           m_type(type)
252     {
253     }
254
255     virtual void begin(QPainter *p, int) {
256         if (m_type & Stroked)
257             p->setPen(Qt::black);
258         else
259             p->setPen(Qt::NoPen);
260
261         if (m_type & Filled)
262             p->setBrush(Qt::red);
263         else
264             p->setBrush(Qt::NoBrush);
265     }
266
267     virtual void draw(QPainter *p, const QRect &rect, int) {
268         switch (m_type & Shapes) {
269         case ArcShape:
270             p->drawArc(rect, 45*16, 120*16);
271             break;
272         case ChordShape:
273             p->drawChord(rect, 45*16, 120*16);
274             break;
275         case PieShape:
276             p->drawPie(rect, 45*16, 120*16);
277             break;
278         case CircleShape:
279             p->drawEllipse(rect);
280             break;
281         }
282     }
283
284     virtual QString name() const {
285         QString fillStroke;
286
287         if ((m_type & (Stroked|Filled)) == (Stroked|Filled)) {
288             fillStroke = QLatin1String("Fill & Outline");
289         } else if (m_type & Stroked) {
290             fillStroke = QLatin1String("Outline");
291         } else if (m_type & Filled) {
292             fillStroke = QLatin1String("Fill");
293         }
294
295         QString shape;
296         if (m_type & PieShape) shape = QLatin1String("drawPie");
297         else if (m_type & ChordShape) shape = QLatin1String("drawChord");
298         else if (m_type & ArcShape) shape = QLatin1String("drawArc");
299         else if (m_type & CircleShape) shape = QLatin1String("drawEllipse");
300
301         return QString::fromLatin1("%1(%2) %3").arg(shape).arg(m_size.width()).arg(fillStroke);
302     }
303
304     uint m_type;
305 };
306
307
308 class DrawScaledImage : public Benchmark
309 {
310 public:
311     DrawScaledImage(const QImage &image, qreal scale, bool asPixmap)
312         : Benchmark(QSize(image.width(), image.height())),
313           m_image(image),
314           m_type(asPixmap ? QLatin1String("Pixmap") : QLatin1String("Image")),
315           m_scale(scale),
316           m_as_pixmap(asPixmap)
317     {
318         m_pixmap = QPixmap::fromImage(m_image);
319     }
320     DrawScaledImage(const QString& type, const QPixmap &pixmap, qreal scale)
321         : Benchmark(QSize(pixmap.width(), pixmap.height())),
322           m_type(type),
323           m_scale(scale),
324           m_as_pixmap(true),
325           m_pixmap(pixmap)
326     {
327     }
328
329     virtual void begin(QPainter *p, int) {
330         p->scale(m_scale, m_scale);
331     }
332
333     virtual void draw(QPainter *p, const QRect &rect, int) {
334         if (m_as_pixmap)
335             p->drawPixmap(rect.topLeft(), m_pixmap);
336         else
337             p->drawImage(rect.topLeft(), m_image);
338     }
339
340     virtual QString name() const {
341         return QString::fromLatin1("draw%4(%1) at scale=%2, depth=%3")
342             .arg(m_size.width())
343             .arg(m_scale)
344             .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth())
345             .arg(m_type);
346    }
347
348 private:
349     QImage m_image;
350     QString m_type;
351     qreal m_scale;
352     bool m_as_pixmap;
353     QPixmap m_pixmap;
354 };
355
356 class DrawTransformedImage : public Benchmark
357 {
358 public:
359     DrawTransformedImage(const QImage &image, bool asPixmap)
360         : Benchmark(QSize(image.width(), image.height())),
361           m_image(image),
362           m_type(asPixmap ? QLatin1String("Pixmap") : QLatin1String("Image")),
363           m_as_pixmap(asPixmap)
364     {
365         m_pixmap = QPixmap::fromImage(m_image);
366     }
367     DrawTransformedImage(const QString& type, const QPixmap &pixmap)
368         : Benchmark(QSize(pixmap.width(), pixmap.height())),
369           m_type(type),
370           m_as_pixmap(true),
371           m_pixmap(pixmap)
372     {
373     }
374
375     virtual void draw(QPainter *p, const QRect &rect, int) {
376         QTransform oldTransform = p->transform();
377         p->translate(0.5 * rect.width() + rect.left(), 0.5 * rect.height() + rect.top());
378         p->shear(0.25, 0.0);
379         p->rotate(5.0);
380         if (m_as_pixmap)
381             p->drawPixmap(-0.5 * rect.width(), -0.5 * rect.height(), m_pixmap);
382         else
383             p->drawImage(-0.5 * rect.width(), -0.5 * rect.height(), m_image);
384         p->setTransform(oldTransform);
385     }
386
387     virtual QString name() const {
388         return QString::fromLatin1("draw%3(%1) w/transform, depth=%2")
389             .arg(m_size.width())
390             .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth())
391             .arg(m_type);
392    }
393
394 private:
395     QImage m_image;
396     QString m_type;
397     bool m_as_pixmap;
398     QPixmap m_pixmap;
399 };
400
401
402 class DrawImage : public Benchmark
403 {
404 public:
405     DrawImage(const QImage &image, bool asPixmap)
406         : Benchmark(QSize(image.width(), image.height())),
407           m_image(image),
408           m_type(asPixmap ? QLatin1String("Pixmap") : QLatin1String("Image")),
409           m_as_pixmap(asPixmap)
410     {
411         m_pixmap = QPixmap::fromImage(image);
412     }
413     DrawImage(const QString& type, const QPixmap &pixmap)
414         : Benchmark(QSize(pixmap.width(), pixmap.height())),
415           m_type(type),
416           m_as_pixmap(true),
417           m_pixmap(pixmap)
418     {
419     }
420
421     virtual void draw(QPainter *p, const QRect &rect, int) {
422         if (m_as_pixmap)
423             p->drawPixmap(rect.topLeft(), m_pixmap);
424         else
425             p->drawImage(rect.topLeft(), m_image);
426     }
427
428     virtual QString name() const {
429         return QString::fromLatin1("draw%2(%1), depth=%3")
430             .arg(m_size.width())
431             .arg(m_type)
432             .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth());
433    }
434
435 private:
436     QImage m_image;
437     QString m_type;
438     bool m_as_pixmap;
439     QPixmap m_pixmap;
440 };
441
442
443 class DrawText : public Benchmark
444 {
445 public:
446     enum Mode {
447         PainterMode,
448         PainterQPointMode,
449         LayoutMode,
450         DocumentMode,
451         PixmapMode
452     };
453
454     DrawText(const QString &text, Mode mode)
455         : Benchmark(QSize()), m_mode(mode), m_text(text), m_document(text), m_layout(text)
456     {
457     }
458
459     virtual void begin(QPainter *p, int iterations) {
460         m_pixmaps.clear();
461         m_currentPixmap = 0;
462         QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height());
463         switch (m_mode) {          
464         case PainterMode:
465             m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
466 //            m_rect = m_rect.translated(-m_rect.topLeft());
467             break;
468         case DocumentMode:
469             m_size = QSize(m_document.size().toSize());
470             break;
471         case PixmapMode:
472             for (int i=0; i<4; ++i) {
473                 m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
474                 QPixmap pixmap = QPixmap(m_size);
475                 pixmap.fill(Qt::transparent);
476                 {
477                     QPainter p(&pixmap);
478                     p.drawText(pixmap.rect(), m_text);
479                 }
480                 m_pixmaps.append(pixmap);
481             }
482             break;
483         case LayoutMode: {
484             QRect r = p->boundingRect(m_bounds, 0, m_text);
485             QStringList lines = m_text.split(QLatin1Char('\n'));
486             int height = 0;
487             int leading = p->fontMetrics().leading();
488             m_layout.beginLayout();
489             for (int i=0; i<lines.size(); ++i) {
490                 QTextLine textLine = m_layout.createLine();
491                 if (textLine.isValid()) {
492                     textLine.setLineWidth(r.width());
493                     textLine.setPosition(QPointF(0, height));
494                     height += leading + textLine.height();
495                 }
496             }
497             m_layout.endLayout();
498             m_layout.setCacheEnabled(true);
499             m_size = m_layout.boundingRect().toRect().size();
500             break;
501         }
502
503         case PainterQPointMode: {
504             QFontMetrics fm(p->font());
505             m_size = QSize(fm.width(m_text, m_text.length()), fm.height());
506             break;
507         }
508
509         }
510     }
511
512     virtual void draw(QPainter *p, const QRect &rect, int)
513     {
514         switch (m_mode) {
515         case PainterMode:
516             p->drawText(rect, 0, m_text);
517             break;
518         case PainterQPointMode:
519             p->drawText(rect.topLeft(), m_text);
520             break;
521         case PixmapMode:
522             p->drawPixmap(rect.topLeft(), m_pixmaps.at(m_currentPixmap));
523             m_currentPixmap = (m_currentPixmap + 1) % m_pixmaps.size();
524             break;
525         case DocumentMode:
526             p->translate(rect.topLeft());
527             m_document.drawContents(p);
528             p->translate(-rect.topLeft());
529             break;
530         case LayoutMode:
531             m_layout.draw(p, rect.topLeft());
532             break;
533         }
534     }
535
536     virtual QString name() const {
537         int letters = m_text.length();
538         int lines = m_text.count(QLatin1Char('\n'));
539         if (lines == 0)
540             lines = 1;
541         QString type;
542         switch (m_mode) {
543         case PainterMode: type = QLatin1String("drawText(rect)"); break;
544         case PainterQPointMode: type = QLatin1String("drawText(point)"); break;
545         case LayoutMode: type = QLatin1String("layout.draw()"); break;
546         case DocumentMode: type = QLatin1String("doc.drawContents()"); break;
547         case PixmapMode: type = QLatin1String("pixmap cached text"); break;
548         }
549
550         return QString::fromLatin1("%3, len=%1, lines=%2")
551             .arg(letters)
552             .arg(lines)
553             .arg(type);
554     }
555
556 private:
557     Mode m_mode;
558     QString m_text;
559     QTextDocument m_document;
560     QTextLayout m_layout;
561
562     QList<QPixmap> m_pixmaps;
563     int m_currentPixmap;
564 };
565
566
567
568
569 class ClippedDrawRectBenchmark : public Benchmark
570 {
571 public:
572     enum ClipType {
573         RectClip,
574         TwoRectRegionClip,
575         EllipseRegionClip,
576         TwoRectPathClip,
577         EllipsePathClip,
578         AAEllipsePathClip,
579         EllipseRegionThenRectClip,
580         EllipsePathThenRectClip
581     };
582
583     ClippedDrawRectBenchmark(int size, ClipType type)
584         : Benchmark(QSize(size, size)), m_type(type)
585     {
586     }
587
588     virtual void begin(QPainter *p, int) {
589         QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height());
590         p->setPen(Qt::NoPen);
591         p->setBrush(Qt::red);
592
593         switch (m_type) {
594         case RectClip:
595             p->setClipRect(m_bounds.adjusted(1, 1, -1, -1));
596             break;
597         case TwoRectRegionClip:
598             p->setClipRegion(QRegion(m_bounds.adjusted(0, 0, -1, -1))
599                              | QRegion(m_bounds.adjusted(1, 1, 0, 0)));
600             break;
601         case EllipseRegionClip:
602             p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse));
603             break;
604         case TwoRectPathClip:
605             {
606                 QPainterPath path;
607                 path.addRect(m_bounds.adjusted(0, 0, -1, -1));
608                 path.addRect(m_bounds.adjusted(1, 1, 0, 0));
609                 path.setFillRule(Qt::WindingFill);
610                 p->setClipPath(path);
611             }
612             break;
613         case EllipsePathClip:
614             {
615                 QPainterPath path;
616                 path.addEllipse(m_bounds);
617                 p->setClipPath(path);
618             }
619             break;
620         case AAEllipsePathClip:
621             {
622                 QPainterPath path;
623                 path.addEllipse(m_bounds);
624                 p->setRenderHint(QPainter::Antialiasing);
625                 p->setClipPath(path);
626                 p->setRenderHint(QPainter::Antialiasing, false);
627             }
628             break;
629         case EllipseRegionThenRectClip:
630             p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse));
631             p->setClipRegion(QRegion(m_bounds.width() / 4,
632                                    m_bounds.height() / 4,
633                                    m_bounds.width() / 2,
634                                    m_bounds.height() / 2), Qt::IntersectClip);
635             break;
636         case EllipsePathThenRectClip:
637             {
638                 QPainterPath path;
639                 path.addEllipse(m_bounds);
640                 p->setClipPath(path);
641                 p->setClipRegion(QRegion(m_bounds.width() / 4,
642                                          m_bounds.height() / 4,
643                                          m_bounds.width() / 2,
644                                          m_bounds.height() / 2), Qt::IntersectClip);
645             }
646             break;
647         }
648     }
649
650     virtual void draw(QPainter *p, const QRect &rect, int) {
651         p->drawRect(rect);
652     }
653
654     virtual QString name() const {
655         QString namedType;
656         switch (m_type) {
657         case RectClip:
658             namedType = QLatin1String("rect");
659             break;
660         case TwoRectRegionClip:
661             namedType = QLatin1String("two-rect-region");
662             break;
663         case EllipseRegionClip:
664             namedType = QLatin1String("ellipse-region");
665             break;
666         case TwoRectPathClip:
667             namedType = QLatin1String("two-rect-path");
668             break;
669         case EllipsePathClip:
670             namedType = QLatin1String("ellipse-path");
671             break;
672         case AAEllipsePathClip:
673             namedType = QLatin1String("aa-ellipse-path");
674             break;
675         case EllipseRegionThenRectClip:
676             namedType = QLatin1String("ellipseregion&rect");
677             break;
678         case EllipsePathThenRectClip:
679             namedType = QLatin1String("ellipsepath&rect");
680             break;
681         }
682         return QString::fromLatin1("%1-clipped-drawRect(%2)").arg(namedType).arg(m_size.width());
683    }
684
685     ClipType m_type;
686 };
687
688 class LinesBenchmark : public Benchmark
689 {
690 public:
691     enum LineType {
692         Horizontal_Integer,
693         Diagonal_Integer,
694         Vertical_Integer,
695         Horizontal_Float,
696         Diagonal_Float,
697         Vertical_Float
698     };
699
700     LinesBenchmark(int length, LineType type)
701         : Benchmark(QSize(qAbs(length), qAbs(length))),
702           m_type(type),
703           m_length(length)
704     {
705
706     }
707
708     virtual void draw(QPainter *p, const QRect &rect, int) {
709         switch (m_type) {
710         case Horizontal_Integer:
711             p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y()));
712             break;
713         case Diagonal_Integer:
714             p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length));
715             break;
716         case Vertical_Integer:
717             p->drawLine(QLine(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length));
718             break;
719         case Horizontal_Float:
720             p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y()));
721             break;
722         case Diagonal_Float:
723             p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length));
724             break;
725         case Vertical_Float:
726             p->drawLine(QLineF(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length));
727             break;
728         }
729     }
730
731     virtual QString name() const {
732         const char *names[] = {
733             "Hor_I",
734             "Diag_I",
735             "Ver_I",
736             "Hor_F",
737             "Diag_F",
738             "Ver_F"
739         };
740         return QString::fromLatin1("drawLine(size=%1,type=%2)").arg(m_length).arg(names[m_type]);
741     }
742
743     LineType m_type;
744     int m_length;
745 };
746
747 #endif // BENCHMARKTESTS_H