1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <QtGui/QGuiApplication>
31#include <QtGui/QPainter>
32#include <QtGui/QImage>
33
34#include <qstatictext.h>
35#include <qpaintengine.h>
36
37#ifdef QT_BUILD_INTERNAL
38#include <private/qstatictext_p.h>
39#endif
40
41// #define DEBUG_SAVE_IMAGE
42
43static inline QImage blankSquare()
44{
45 // a "blank" square; we compare against in our testfunctions to verify
46 // that we have actually painted something
47 QPixmap pm(1000, 1000);
48 pm.fill(fillColor: Qt::white);
49 return pm.toImage();
50}
51
52class tst_QStaticText: public QObject
53{
54 Q_OBJECT
55public:
56 tst_QStaticText() : m_whiteSquare(blankSquare()) {}
57
58private slots:
59 void constructionAndDestruction();
60 void drawToPoint_data();
61 void drawToPoint();
62 void drawToRect_data();
63 void drawToRect();
64 void compareToDrawText_data();
65 void compareToDrawText();
66 void setFont();
67 void setTextWidth();
68 void prepareToCorrectData();
69 void prepareToWrongData();
70
71 void copyConstructor();
72
73 void translatedPainter();
74 void rotatedPainter();
75 void scaledPainter();
76 void projectedPainter();
77#if 0
78 void rotatedScaledAndTranslatedPainter_data();
79 void rotatedScaledAndTranslatedPainter();
80#endif
81 void transformationChanged();
82
83 void plainTextVsRichText();
84
85 void setPenPlainText_data();
86 void setPenPlainText();
87 void setPenRichText();
88 void richTextOverridesPen();
89
90 void drawStruckOutText();
91 void drawOverlinedText();
92 void drawUnderlinedText();
93
94 void unprintableCharacter_qtbug12614();
95
96#ifdef QT_BUILD_INTERNAL
97 void underlinedColor_qtbug20159();
98 void textDocumentColor();
99#endif
100
101 void multiLine();
102
103 void size_qtbug65836();
104
105private:
106 bool supportsTransformations() const;
107
108 const QImage m_whiteSquare;
109};
110
111Q_DECLARE_METATYPE(QImage::Format);
112
113void tst_QStaticText::constructionAndDestruction()
114{
115 QStaticText text("My text");
116}
117
118void tst_QStaticText::copyConstructor()
119{
120 QStaticText text(QLatin1String("My text"));
121
122 QTextOption textOption(Qt::AlignRight);
123 text.setTextOption(textOption);
124
125 text.setPerformanceHint(QStaticText::AggressiveCaching);
126 text.setTextWidth(123.456);
127 text.setTextFormat(Qt::PlainText);
128
129 QStaticText copiedText(text);
130 copiedText.setText(QLatin1String("Other text"));
131
132 QCOMPARE(copiedText.textOption().alignment(), Qt::AlignRight);
133 QCOMPARE(copiedText.performanceHint(), QStaticText::AggressiveCaching);
134 QCOMPARE(copiedText.textWidth(), 123.456);
135 QCOMPARE(copiedText.textFormat(), Qt::PlainText);
136
137 QStaticText otherCopiedText(copiedText);
138 otherCopiedText.setTextWidth(789);
139
140 QCOMPARE(otherCopiedText.text(), QString::fromLatin1("Other text"));
141}
142
143Q_DECLARE_METATYPE(QStaticText::PerformanceHint)
144void tst_QStaticText::drawToPoint_data()
145{
146 QTest::addColumn<QStaticText::PerformanceHint>(name: "performanceHint");
147
148 QTest::newRow(dataTag: "Moderate caching") << QStaticText::ModerateCaching;
149 QTest::newRow(dataTag: "Aggressive caching") << QStaticText::AggressiveCaching;
150}
151
152void tst_QStaticText::drawToPoint()
153{
154 QFETCH(QStaticText::PerformanceHint, performanceHint);
155
156 QPixmap imageDrawText(1000, 1000);
157 imageDrawText.fill(fillColor: Qt::white);
158 {
159 QPainter p(&imageDrawText);
160 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
161 }
162
163 QPixmap imageDrawStaticText(1000, 1000);
164 imageDrawStaticText.fill(fillColor: Qt::white);
165 {
166 QPainter p(&imageDrawStaticText);
167 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
168 text.setTextFormat(Qt::PlainText);
169 text.setPerformanceHint(performanceHint);
170 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
171 }
172
173 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
174 QCOMPARE(imageDrawStaticText, imageDrawText);
175}
176
177void tst_QStaticText::drawToRect_data()
178{
179 QTest::addColumn<QStaticText::PerformanceHint>(name: "performanceHint");
180
181 QTest::newRow(dataTag: "Moderate caching") << QStaticText::ModerateCaching;
182 QTest::newRow(dataTag: "Aggressive caching") << QStaticText::AggressiveCaching;
183}
184
185void tst_QStaticText::drawToRect()
186{
187 QFETCH(QStaticText::PerformanceHint, performanceHint);
188
189 QPixmap imageDrawText(1000, 1000);
190 imageDrawText.fill(fillColor: Qt::white);
191 {
192 QPainter p(&imageDrawText);
193 p.drawText(r: QRectF(11, 12, 10, 500), text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
194 }
195
196 QPixmap imageDrawStaticText(1000, 1000);
197 imageDrawStaticText.fill(fillColor: Qt::white);
198 {
199 QPainter p(&imageDrawStaticText);
200 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
201 text.setTextWidth(10),
202 p.setClipRect(QRectF(11, 12, 10, 500));
203 text.setPerformanceHint(performanceHint);
204 text.setTextFormat(Qt::PlainText);
205 p.drawStaticText(topLeftPosition: QPointF(11, 12), staticText: text);
206 }
207
208#if defined(DEBUG_SAVE_IMAGE)
209 imageDrawText.save("drawToRect_imageDrawText.png");
210 imageDrawStaticText.save("drawToRect_imageDrawStaticText.png");
211#endif
212
213 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
214 QCOMPARE(imageDrawStaticText, imageDrawText);
215}
216
217void tst_QStaticText::compareToDrawText_data()
218{
219 QTest::addColumn<QFont>(name: "font");
220
221 QTest::newRow(dataTag: "default") << QFont();
222 QFont sansserif; sansserif.setStyleHint(QFont::SansSerif);
223 QFont serif; serif.setStyleHint(QFont::Serif);
224 QFont monospace; monospace.setStyleHint(QFont::Monospace);
225 QTest::newRow(dataTag: "sans-serif") << QFont(sansserif.defaultFamily());
226 QTest::newRow(dataTag: "serif") << QFont(serif.defaultFamily());
227 QTest::newRow(dataTag: "monospace") << QFont(monospace.defaultFamily());
228}
229
230void tst_QStaticText::compareToDrawText()
231{
232 QFETCH(QFont, font);
233
234 QPixmap imageDrawText(1000, 1000);
235 imageDrawText.fill(fillColor: Qt::white);
236 {
237 QPainter p(&imageDrawText);
238 p.setFont(font);
239 p.drawText(r: QRectF(11, 12, 30, 500), text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
240 }
241
242 QPixmap imageDrawStaticPlainText(1000, 1000);
243 imageDrawStaticPlainText.fill(fillColor: Qt::white);
244 {
245 QPainter p(&imageDrawStaticPlainText);
246 p.setFont(font);
247 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
248 text.setTextWidth(10),
249 p.setClipRect(QRectF(11, 12, 30, 500));
250 text.setTextFormat(Qt::PlainText);
251 p.drawStaticText(topLeftPosition: QPointF(11, 12), staticText: text);
252 }
253
254 QPixmap imageDrawStaticRichText(1000, 1000);
255 imageDrawStaticRichText.fill(fillColor: Qt::white);
256 {
257 QPainter p(&imageDrawStaticRichText);
258 p.setFont(font);
259 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
260 text.setTextWidth(10),
261 p.setClipRect(QRectF(11, 12, 30, 500));
262 text.setTextFormat(Qt::RichText);
263 p.drawStaticText(topLeftPosition: QPointF(11, 12), staticText: text);
264 }
265
266#if defined(DEBUG_SAVE_IMAGE)
267 imageDrawText.save("compareToDrawText_imageDrawText.png");
268 imageDrawStaticText.save("compareToDrawText_imageDrawStaticPlainText.png");
269 imageDrawStaticText.save("compareToDrawText_imageDrawStaticRichText.png");
270#endif
271
272 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
273 QCOMPARE(imageDrawStaticPlainText, imageDrawText);
274 QCOMPARE(imageDrawStaticRichText, imageDrawText);
275}
276
277void tst_QStaticText::prepareToCorrectData()
278{
279 QTransform transform;
280 transform.scale(sx: 2.0, sy: 2.0);
281 transform.translate(dx: 100, dy: 10);
282 transform.rotate(a: 90, axis: Qt::ZAxis);
283
284 QPixmap imageDrawText(1000, 1000);
285 imageDrawText.fill(fillColor: Qt::white);
286 {
287 QPainter p(&imageDrawText);
288 p.setTransform(transform);
289 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
290 }
291
292 QPixmap imageDrawStaticText(1000, 1000);
293 imageDrawStaticText.fill(fillColor: Qt::white);
294 {
295 QPainter p(&imageDrawStaticText);
296 p.setTransform(transform);
297 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
298 text.prepare(matrix: transform, font: p.font());
299 text.setTextFormat(Qt::PlainText);
300 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
301 }
302
303#if defined(DEBUG_SAVE_IMAGE)
304 imageDrawText.save("prepareToCorrectData_imageDrawText.png");
305 imageDrawStaticText.save("prepareToCorrectData_imageDrawStaticText.png");
306#endif
307
308 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
309
310 if (!supportsTransformations())
311 QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
312 QCOMPARE(imageDrawStaticText, imageDrawText);
313}
314
315void tst_QStaticText::prepareToWrongData()
316{
317 QTransform transform;
318 transform.scale(sx: 2.0, sy: 2.0);
319 transform.rotate(a: 90, axis: Qt::ZAxis);
320
321 QPixmap imageDrawText(1000, 1000);
322 imageDrawText.fill(fillColor: Qt::white);
323 {
324 QPainter p(&imageDrawText);
325 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
326 }
327
328 QPixmap imageDrawStaticText(1000, 1000);
329 imageDrawStaticText.fill(fillColor: Qt::white);
330 {
331 QPainter p(&imageDrawStaticText);
332 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
333 text.prepare(matrix: transform, font: p.font());
334 text.setTextFormat(Qt::PlainText);
335 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
336 }
337
338 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
339 QCOMPARE(imageDrawStaticText, imageDrawText);
340}
341
342
343void tst_QStaticText::setFont()
344{
345 QFont font = QGuiApplication::font();
346 font.setBold(true);
347 font.setPointSize(28);
348
349 QPixmap imageDrawText(1000, 1000);
350 imageDrawText.fill(fillColor: Qt::white);
351 {
352 QPainter p(&imageDrawText);
353 p.drawText(r: QRectF(0, 0, 1000, 1000), flags: 0, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
354
355 p.setFont(font);
356 p.drawText(r: QRectF(11, 120, 1000, 1000), flags: 0, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
357 }
358
359 QPixmap imageDrawStaticText(1000, 1000);
360 imageDrawStaticText.fill(fillColor: Qt::white);
361 {
362 QPainter p(&imageDrawStaticText);
363
364 QStaticText text;
365 text.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
366 text.setTextFormat(Qt::PlainText);
367
368 p.drawStaticText(x: 0, y: 0, staticText: text);
369
370 p.setFont(font);
371 p.drawStaticText(x: 11, y: 120, staticText: text);
372 }
373
374#if defined(DEBUG_SAVE_IMAGE)
375 imageDrawText.save("setFont_imageDrawText.png");
376 imageDrawStaticText.save("setFont_imageDrawStaticText.png");
377#endif
378
379 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
380 QCOMPARE(imageDrawStaticText, imageDrawText);
381}
382
383void tst_QStaticText::setTextWidth()
384{
385 QPixmap imageDrawText(1000, 1000);
386 imageDrawText.fill(fillColor: Qt::white);
387 {
388 QPainter p(&imageDrawText);
389 p.drawText(r: QRectF(11, 12, 10, 500), text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
390 }
391
392 QPixmap imageDrawStaticText(1000, 1000);
393 imageDrawStaticText.fill(fillColor: Qt::white);
394 {
395 QPainter p(&imageDrawStaticText);
396 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
397 text.setTextWidth(10);
398 p.setClipRect(QRectF(11, 12, 10, 500));
399 p.drawStaticText(topLeftPosition: QPointF(11, 12), staticText: text);
400 }
401
402 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
403 QCOMPARE(imageDrawStaticText, imageDrawText);
404}
405
406void tst_QStaticText::translatedPainter()
407{
408 QPixmap imageDrawText(1000, 1000);
409 imageDrawText.fill(fillColor: Qt::white);
410 {
411 QPainter p(&imageDrawText);
412 p.translate(dx: 100, dy: 200);
413
414 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
415 }
416
417 QPixmap imageDrawStaticText(1000, 1000);
418 imageDrawStaticText.fill(fillColor: Qt::white);
419 {
420 QPainter p(&imageDrawStaticText);
421 p.translate(dx: 100, dy: 200);
422
423 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
424 text.setTextFormat(Qt::PlainText);
425
426 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
427 }
428
429 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
430 QCOMPARE(imageDrawStaticText, imageDrawText);
431}
432
433bool tst_QStaticText::supportsTransformations() const
434{
435 QPixmap pm(10, 10);
436 QPainter p(&pm);
437 return p.paintEngine()->type() != QPaintEngine::OpenGL;
438}
439
440void tst_QStaticText::rotatedPainter()
441{
442 QPixmap imageDrawText(1000, 1000);
443 imageDrawText.fill(fillColor: Qt::white);
444 {
445 QPainter p(&imageDrawText);
446 p.rotate(a: 30.0);
447 p.drawText(r: QRectF(0, 0, 1000, 100), flags: 0, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
448 }
449
450 QPixmap imageDrawStaticText(1000, 1000);
451 imageDrawStaticText.fill(fillColor: Qt::white);
452 {
453 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
454 text.setTextFormat(Qt::PlainText);
455
456 QPainter p(&imageDrawStaticText);
457 p.rotate(a: 30.0);
458 p.drawStaticText(p: QPoint(0, 0), staticText: text);
459 }
460
461#if defined(DEBUG_SAVE_IMAGE)
462 imageDrawText.save("rotatedPainter_imageDrawText.png");
463 imageDrawStaticText.save("rotatedPainter_imageDrawStaticText.png");
464#endif
465
466 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
467
468#ifdef Q_OS_ANDROID
469 QEXPECT_FAIL("", "QTBUG-69218", Continue);
470#endif
471 if (!supportsTransformations())
472 QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
473 QCOMPARE(imageDrawStaticText, imageDrawText);
474}
475
476void tst_QStaticText::scaledPainter()
477{
478 QPixmap imageDrawText(1000, 1000);
479 imageDrawText.fill(fillColor: Qt::white);
480 {
481 QPainter p(&imageDrawText);
482 p.scale(sx: 2.0, sy: 0.2);
483
484 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
485 }
486
487 QPixmap imageDrawStaticText(1000, 1000);
488 imageDrawStaticText.fill(fillColor: Qt::white);
489 {
490 QPainter p(&imageDrawStaticText);
491 p.scale(sx: 2.0, sy: 0.2);
492
493 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
494 text.setTextFormat(Qt::PlainText);
495
496 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
497 }
498
499 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
500
501 if (!supportsTransformations())
502 QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
503 QCOMPARE(imageDrawStaticText, imageDrawText);
504}
505
506void tst_QStaticText::projectedPainter()
507{
508 QTransform transform;
509 transform.rotate(a: 90, axis: Qt::XAxis);
510
511 QPixmap imageDrawText(1000, 1000);
512 imageDrawText.fill(fillColor: Qt::white);
513 {
514 QPainter p(&imageDrawText);
515 p.setTransform(transform);
516
517 p.drawText(x: 11, y: 12, s: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
518 }
519
520 QPixmap imageDrawStaticText(1000, 1000);
521 imageDrawStaticText.fill(fillColor: Qt::white);
522 {
523 QPainter p(&imageDrawStaticText);
524 p.setTransform(transform);
525
526 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
527 text.setTextFormat(Qt::PlainText);
528
529 p.drawStaticText(topLeftPosition: QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), staticText: text);
530 }
531
532 QCOMPARE(imageDrawStaticText, imageDrawText);
533}
534
535#if 0
536void tst_QStaticText::rotatedScaledAndTranslatedPainter_data()
537{
538 QTest::addColumn<qreal>("offset");
539
540 for (int i=0; i<100; ++i) {
541 qreal offset = 300 + i / 100.;
542 QTest::newRow(QByteArray::number(offset).constData()) << offset;
543 }
544}
545
546void tst_QStaticText::rotatedScaledAndTranslatedPainter()
547{
548 QFETCH(qreal, offset);
549
550 QPixmap imageDrawText(1000, 1000);
551 imageDrawText.fill(Qt::white);
552 {
553 QPainter p(&imageDrawText);
554 p.translate(offset, 0);
555 p.rotate(45.0);
556 p.scale(2.0, 2.0);
557 p.translate(100, 200);
558
559 p.drawText(11, 12, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
560 }
561
562 QPixmap imageDrawStaticText(1000, 1000);
563 imageDrawStaticText.fill(Qt::white);
564 {
565 QPainter p(&imageDrawStaticText);
566 p.translate(offset, 0);
567 p.rotate(45.0);
568 p.scale(2.0, 2.0);
569 p.translate(100, 200);
570
571 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
572 text.setTextFormat(Qt::PlainText);
573
574 p.drawStaticText(QPointF(11, 12 - QFontMetricsF(p.font()).ascent()), text);
575 }
576
577#if defined(DEBUG_SAVE_IMAGE)
578 imageDrawText.save("rotatedScaledAndPainter_imageDrawText.png");
579 imageDrawStaticText.save("rotatedScaledAndPainter_imageDrawStaticText.png");
580#endif
581
582 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
583
584 if (!supportsTransformations())
585 QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
586 QCOMPARE(imageDrawStaticText, imageDrawText);
587}
588#endif
589
590void tst_QStaticText::transformationChanged()
591{
592 QPixmap imageDrawText(1000, 1000);
593 imageDrawText.fill(fillColor: Qt::white);
594 {
595 QPainter p(&imageDrawText);
596 p.rotate(a: 33.0);
597 p.scale(sx: 0.5, sy: 0.7);
598
599 p.drawText(r: QRectF(0, 0, 1000, 1000), flags: 0, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
600
601 p.scale(sx: 2.0, sy: 2.5);
602 p.drawText(r: QRectF(0, 0, 1000, 1000), flags: 0, text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
603 }
604
605 QPixmap imageDrawStaticText(1000, 1000);
606 imageDrawStaticText.fill(fillColor: Qt::white);
607 {
608 QPainter p(&imageDrawStaticText);
609 p.rotate(a: 33.0);
610 p.scale(sx: 0.5, sy: 0.7);
611
612 QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
613 text.setTextFormat(Qt::PlainText);
614
615 p.drawStaticText(topLeftPosition: QPointF(0, 0), staticText: text);
616
617 p.scale(sx: 2.0, sy: 2.5);
618 p.drawStaticText(topLeftPosition: QPointF(0, 0), staticText: text);
619 }
620
621#if defined(DEBUG_SAVE_IMAGE)
622 imageDrawText.save("transformationChanged_imageDrawText.png");
623 imageDrawStaticText.save("transformationChanged_imageDrawStaticText.png");
624#endif
625
626 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
627
628#ifdef Q_OS_ANDROID
629 QEXPECT_FAIL("", "QTBUG-69220", Continue);
630#endif
631 if (!supportsTransformations())
632 QEXPECT_FAIL("", "Graphics system does not support transformed text on this platform", Abort);
633 QCOMPARE(imageDrawStaticText, imageDrawText);
634}
635
636void tst_QStaticText::plainTextVsRichText()
637{
638 QPixmap imagePlainText(1000, 1000);
639 imagePlainText.fill(fillColor: Qt::white);
640 {
641 QPainter p(&imagePlainText);
642
643 QStaticText staticText;
644 staticText.setText("FOObar");
645 staticText.setTextFormat(Qt::PlainText);
646
647 p.drawStaticText(x: 10, y: 10, staticText);
648 }
649
650 QPixmap imageRichText(1000, 1000);
651 imageRichText.fill(fillColor: Qt::white);
652 {
653 QPainter p(&imageRichText);
654
655 QStaticText staticText;
656 staticText.setText("<html><body>FOObar</body></html>");
657 staticText.setTextFormat(Qt::RichText);
658
659 p.drawStaticText(x: 10, y: 10, staticText);
660 }
661
662#if defined(DEBUG_SAVE_IMAGE)
663 imagePlainText.save("plainTextVsRichText_imagePlainText.png");
664 imageRichText.save("plainTextVsRichText_imageRichText.png");
665#endif
666
667 QVERIFY(imagePlainText.toImage() != m_whiteSquare);
668 QCOMPARE(imagePlainText, imageRichText);
669}
670
671static bool checkPixels(const QImage &image,
672 Qt::GlobalColor expectedColor1, Qt::GlobalColor expectedColor2,
673 QByteArray *errorMessage)
674{
675 const QRgb expectedRgb1 = QColor(expectedColor1).rgba();
676 const QRgb expectedRgb2 = QColor(expectedColor2).rgba();
677
678 for (int x = 0, w = image.width(); x < w; ++x) {
679 for (int y = 0, h = image.height(); y < h; ++y) {
680 const QRgb pixel = image.pixel(x, y);
681 if (pixel != expectedRgb1 && pixel != expectedRgb2) {
682 QString message;
683 QDebug(&message) << "Color mismatch in image" << image
684 << "at" << x << ',' << y << ':' << Qt::showbase << Qt::hex << pixel
685 << "(expected: " << expectedRgb1 << ',' << expectedRgb2 << ')';
686 *errorMessage = message.toLocal8Bit();
687 return false;
688 }
689 }
690 }
691 return true;
692}
693
694void tst_QStaticText::setPenPlainText_data()
695{
696 QTest::addColumn<QImage::Format>(name: "format");
697
698 QTest::newRow(dataTag: "argb32pm") << QImage::Format_ARGB32_Premultiplied;
699 QTest::newRow(dataTag: "rgb32") << QImage::Format_RGB32;
700 QTest::newRow(dataTag: "rgba8888pm") << QImage::Format_RGBA8888_Premultiplied;
701 QTest::newRow(dataTag: "rgbx8888") << QImage::Format_RGBX8888;
702}
703
704void tst_QStaticText::setPenPlainText()
705{
706 QFETCH(QImage::Format, format);
707
708 QFont font = QGuiApplication::font();
709 font.setStyleStrategy(QFont::NoAntialias);
710
711 QFontMetricsF fm(font);
712 QImage image(qCeil(v: fm.horizontalAdvance(string: "XXXXX")), qCeil(v: fm.height()), format);
713 image.fill(color: Qt::white);
714 {
715 QPainter p(&image);
716 p.setFont(font);
717 p.setPen(Qt::yellow);
718
719 QStaticText staticText("XXXXX");
720 staticText.setTextFormat(Qt::PlainText);
721 p.drawStaticText(x: 0, y: 0, staticText);
722 }
723
724 QByteArray errorMessage;
725 QVERIFY2(checkPixels(image, Qt::yellow, Qt::white, &errorMessage),
726 errorMessage.constData());
727}
728
729void tst_QStaticText::setPenRichText()
730{
731 QFont font = QGuiApplication::font();
732 font.setStyleStrategy(QFont::NoAntialias);
733
734 QFontMetricsF fm(font);
735 QPixmap image(qCeil(v: fm.horizontalAdvance(string: "XXXXX")), qCeil(v: fm.height()));
736 image.fill(fillColor: Qt::white);
737 {
738 QPainter p(&image);
739 p.setFont(font);
740 p.setPen(Qt::green);
741
742 QStaticText staticText;
743 staticText.setText("<html><body>XXXXX</body></html>");
744 staticText.setTextFormat(Qt::RichText);
745 p.drawStaticText(x: 0, y: 0, staticText);
746 }
747
748 QByteArray errorMessage;
749 QVERIFY2(checkPixels(image.toImage(), Qt::green, Qt::white, &errorMessage),
750 errorMessage.constData());
751}
752
753void tst_QStaticText::richTextOverridesPen()
754{
755 QFont font = QGuiApplication::font();
756 font.setStyleStrategy(QFont::NoAntialias);
757
758 QFontMetricsF fm(font);
759 QPixmap image(qCeil(v: fm.horizontalAdvance(string: "XXXXX")), qCeil(v: fm.height()));
760 image.fill(fillColor: Qt::white);
761 {
762 QPainter p(&image);
763 p.setFont(font);
764 p.setPen(Qt::green);
765
766 QStaticText staticText;
767 staticText.setText("<html><body><font color=\"#ff0000\">XXXXX</font></body></html>");
768 staticText.setTextFormat(Qt::RichText);
769 p.drawStaticText(x: 0, y: 0, staticText);
770 }
771
772 QByteArray errorMessage;
773 QVERIFY2(checkPixels(image.toImage(), Qt::red, Qt::white, &errorMessage),
774 errorMessage.constData());
775}
776
777void tst_QStaticText::drawStruckOutText()
778{
779 QPixmap imageDrawText(1000, 1000);
780 QPixmap imageDrawStaticText(1000, 1000);
781
782 imageDrawText.fill(fillColor: Qt::white);
783 imageDrawStaticText.fill(fillColor: Qt::white);
784
785 QString s = QString::fromLatin1(str: "Foobar");
786
787 QFont font;
788 font.setStrikeOut(true);
789 font.setStyleStrategy(QFont::ForceIntegerMetrics);
790
791 {
792 QPainter p(&imageDrawText);
793 p.setFont(font);
794 p.drawText(p: QPointF(50, 50), s);
795 }
796
797 {
798 QPainter p(&imageDrawStaticText);
799 QStaticText text = QStaticText(s);
800 p.setFont(font);
801 p.drawStaticText(topLeftPosition: QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), staticText: text);
802 }
803
804#if defined(DEBUG_SAVE_IMAGE)
805 imageDrawText.save("drawStruckOutText_imageDrawText.png");
806 imageDrawStaticText.save("drawStruckOutText_imageDrawStaticText.png");
807#endif
808
809 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
810 QCOMPARE(imageDrawText, imageDrawStaticText);
811}
812
813void tst_QStaticText::drawOverlinedText()
814{
815 QPixmap imageDrawText(1000, 1000);
816 QPixmap imageDrawStaticText(1000, 1000);
817
818 imageDrawText.fill(fillColor: Qt::white);
819 imageDrawStaticText.fill(fillColor: Qt::white);
820
821 QString s = QString::fromLatin1(str: "Foobar");
822
823 QFont font;
824 font.setOverline(true);
825 font.setStyleStrategy(QFont::ForceIntegerMetrics);
826
827 {
828 QPainter p(&imageDrawText);
829 p.setFont(font);
830 p.drawText(p: QPointF(50, 50), s);
831 }
832
833 {
834 QPainter p(&imageDrawStaticText);
835 QStaticText text = QStaticText(s);
836 p.setFont(font);
837 p.drawStaticText(topLeftPosition: QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), staticText: text);
838 }
839
840#if defined(DEBUG_SAVE_IMAGE)
841 imageDrawText.save("drawOverlinedText_imageDrawText.png");
842 imageDrawStaticText.save("drawOverlinedText_imageDrawStaticText.png");
843#endif
844
845 QVERIFY(imageDrawText.toImage() != m_whiteSquare);
846 QCOMPARE(imageDrawText, imageDrawStaticText);
847}
848
849void tst_QStaticText::drawUnderlinedText()
850{
851 QPixmap imageDrawText(1000, 1000);
852 QPixmap imageDrawStaticText(1000, 1000);
853
854 imageDrawText.fill(fillColor: Qt::white);
855 imageDrawStaticText.fill(fillColor: Qt::white);
856
857 QString s = QString::fromLatin1(str: "Foobar");
858
859 QFont font;
860 font.setUnderline(true);
861 font.setStyleStrategy(QFont::ForceIntegerMetrics);
862
863 {
864 QPainter p(&imageDrawText);
865 p.setFont(font);
866 p.drawText(p: QPointF(50, 50), s);
867 }
868
869 {
870 QPainter p(&imageDrawStaticText);
871 QStaticText text = QStaticText(s);
872 p.setFont(font);
873 p.drawStaticText(topLeftPosition: QPointF(50, 50 - QFontMetricsF(p.font()).ascent()), staticText: text);
874 }
875
876#if defined(DEBUG_SAVE_IMAGE)
877 imageDrawText.save("drawUnderlinedText_imageDrawText.png");
878 imageDrawStaticText.save("drawUnderlinedText_imageDrawStaticText.png");
879#endif
880
881 QCOMPARE(imageDrawText, imageDrawStaticText);
882}
883
884void tst_QStaticText::unprintableCharacter_qtbug12614()
885{
886 QString s(QChar(0x200B)); // U+200B, ZERO WIDTH SPACE
887
888 QStaticText staticText(s);
889
890 QVERIFY(staticText.size().isValid()); // Force layout. Should not crash.
891}
892
893#ifdef QT_BUILD_INTERNAL
894void tst_QStaticText::underlinedColor_qtbug20159()
895{
896 QString multiScriptText;
897 multiScriptText += QChar(0x0410); // Cyrillic 'A'
898 multiScriptText += QLatin1Char('A');
899
900 QStaticText staticText(multiScriptText);
901
902 QFont font;
903 font.setUnderline(true);
904
905 staticText.prepare(matrix: QTransform(), font);
906
907 QStaticTextPrivate *d = QStaticTextPrivate::get(q: &staticText);
908 QCOMPARE(d->itemCount, 2);
909
910 // The pen should not be marked as dirty when drawing the underline
911 QVERIFY(!d->items[0].color.isValid());
912 QVERIFY(!d->items[1].color.isValid());
913}
914
915void tst_QStaticText::textDocumentColor()
916{
917 QStaticText staticText("A<font color=\"red\">B</font>");
918 staticText.setTextFormat(Qt::RichText);
919 staticText.prepare();
920
921 QStaticTextPrivate *d = QStaticTextPrivate::get(q: &staticText);
922 QCOMPARE(d->itemCount, 2);
923
924 // The pen should not be marked as dirty when drawing the underline
925 QVERIFY(!d->items[0].color.isValid());
926 QVERIFY(d->items[1].color.isValid());
927
928 QCOMPARE(d->items[1].color, QColor(Qt::red));
929}
930#endif
931
932class TestPaintEngine: public QPaintEngine
933{
934public:
935 void drawTextItem(const QPointF &p, const QTextItem &) override
936 {
937 differentVerticalPositions.insert(value: qRound(d: p.y()));
938 }
939
940 void updateState(const QPaintEngineState &) override {}
941
942 void drawPolygon(const QPointF *, int , PolygonDrawMode ) override {}
943
944 bool begin(QPaintDevice *) override { return true; }
945 bool end() override { return true; }
946 void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) override {}
947 Type type() const override
948 {
949 return User;
950 }
951
952 QSet<int> differentVerticalPositions;
953};
954
955class TestPixmap: public QPixmap
956{
957public:
958 TestPixmap(int w, int h) : QPixmap(w, h), testPaintEngine(new TestPaintEngine) {}
959 ~TestPixmap() { delete testPaintEngine; }
960
961 QPaintEngine *paintEngine() const
962 {
963 return testPaintEngine;
964 }
965
966 TestPaintEngine *testPaintEngine;
967};
968
969void tst_QStaticText::multiLine()
970{
971 TestPixmap pixmap(100, 100);
972
973 TestPaintEngine *paintEngine = pixmap.testPaintEngine;
974
975 {
976 QPainter p(&pixmap);
977 QStaticText text;
978 text.setText(QLatin1String("line 1") + QChar(QChar::LineSeparator) + QLatin1String("line 2"));
979 p.drawStaticText(x: 0, y: 0, staticText: text);
980 }
981
982 QCOMPARE(paintEngine->differentVerticalPositions.size(), 2);
983}
984
985void tst_QStaticText::size_qtbug65836()
986{
987 const QString text = QLatin1String("Lorem ipsum dolor sit amet, "
988 "consectetur adipiscing elit.");
989 QFont font("Courier");
990 font.setPixelSize(15);
991
992 {
993 QStaticText st1(text);
994 st1.setTextFormat(Qt::PlainText);
995 st1.prepare(matrix: QTransform(), font);
996
997 QStaticText st2(text);
998 st2.setTextFormat(Qt::RichText);
999 QTextOption opt;
1000 opt.setWrapMode(QTextOption::NoWrap);
1001 st2.setTextOption(opt);
1002 st2.prepare(matrix: QTransform(), font);
1003
1004 QCOMPARE(st1.size(), st2.size());
1005 }
1006
1007 {
1008 QStaticText st1(text);
1009 st1.setTextFormat(Qt::PlainText);
1010 st1.setTextWidth(10.0);
1011 st1.prepare(matrix: QTransform(), font);
1012
1013 QStaticText st2(text);
1014 st2.setTextFormat(Qt::RichText);
1015 st2.setTextWidth(10.0);
1016 st2.prepare(matrix: QTransform(), font);
1017
1018 QCOMPARE(st1.size(), st2.size());
1019 }
1020}
1021
1022QTEST_MAIN(tst_QStaticText)
1023#include "tst_qstatictext.moc"
1024

source code of qtbase/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp